ProjectOpenSea / opensea-js

TypeScript SDK for the OpenSea marketplace
https://docs.opensea.io/reference
MIT License
2.28k stars 964 forks source link

Error: API Error 400: You cannot access body after reading from request's data stream #565

Closed henry1jin closed 2 years ago

henry1jin commented 2 years ago

When calling openseaSDK.createSellOrder, getting this error and not sure why.

henry1jin commented 2 years ago

That link is looking mighty phishy.

davidseroussi commented 2 years ago

getting the same error when calling createBuyOrder

esteban-OpenSea commented 2 years ago

Just deleted the bot comment, sorry about that.

Can you send over specific steps so I can reproduce? Also, is this happening for both sellOrder and buyOrder?

plondon commented 2 years ago

Hi @esteban-OpenSea,

I've also noticed this as well. Here is an example request:

curl https://testnets-api.opensea.io/api/v2/orders/rinkeby/seaport/offers -X POST --data-raw '{"parameters":{"offerer":"0xd5E4EC33d198c57598BE0CA5e78772a4098A2cF6","zone":"0x9b814233894cd227f561b78cc65891aa55c62ad2","zoneHash":"0x3000000000000000000000000000000000000000000000000000000000000000","startTime":"1655418624","endTime":"1655505024","orderType":0,"offer":[{"itemType":1,"token":"0xc778417e063141139fce010982780140aa0cd5ab","identifierOrCriteria":"0","startAmount":"1000000000000000","endAmount":"1000000000000000"}],"consideration":[{"itemType":2,"token":"0xb74bf94049d2c01f8805b8b15db0909168cabf46","identifierOrCriteria":"271","startAmount":"1","endAmount":"1","recipient":"0xd5E4EC33d198c57598BE0CA5e78772a4098A2cF6"},{"itemType":1,"token":"0xc778417e063141139fce010982780140aa0cd5ab","identifierOrCriteria":"0","startAmount":"25000000000000","endAmount":"25000000000000","recipient":"0x0000000000000000000000000000000000000000"}],"totalOriginalConsiderationItems":2,"salt":"0x84d51b5b68c414392f80eeb33c0b6ab4","conduitKey":"0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000","counter":0},"signature":"0x538492d5ab4f260190e6a819b329d731d869e81ebac6aae35aecd1bd5bd83181479cdec7fb059af83f3b8cd9bd2751c6e526b865beedb8d3ad5e334345734296"}' -H 'X-API-KEY: '

{"errors":["You cannot access body after reading from request's data stream"]}%

davidseroussi commented 2 years ago

It's actually because of the url. In the repo, the basePath is https://api.opensea.io/api/v2/ but it should be https://api.opensea.io/v2/. So the final url is https://api.opensea.io/v2/orders/ethereum/seaport/offers

plondon commented 2 years ago

Do you need to call testnets-api if the network is rinkeby?

davidseroussi commented 2 years ago

yes it would be https://testnets-api.opensea.io/v2/orders/rinkeby/seaport/offers

plondon commented 2 years ago

@davidseroussi I think both urls should work actually. Would you mind posting a successful request with the order data?

davidseroussi commented 2 years ago

@plondon sure, this payload returned
{ "errors": [ "You cannot access body after reading from request's data stream" ] }
using /api/v2/offers, but returned the successful order using /v2/offers

{
        "parameters": {
            "offerer": "0xb040d6f5Ea06FBdB221004C1F5a8885D98EBdEa3",
            "offer": [{
                "itemType": 1,
                "token": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
                "identifierOrCriteria": 0,
                "startAmount": 100000000000000000,
                "endAmount": 100000000000000000
            }],
            "consideration": [{
                "itemType": 2,
                "token": "0x0Cfb5d82BE2b949e8fa73A656dF91821E2aD99FD",
                "identifierOrCriteria": 281479271686476,
                "startAmount": 1,
                "endAmount": 1,
                "recipient": "0xb040d6f5Ea06FBdB221004C1F5a8885D98EBdEa3"
            }, {
                "itemType": 1,
                "token": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
                "identifierOrCriteria": 0,
                "startAmount": 2500000000000000,
                "endAmount": 2500000000000000,
                "recipient": "0x8De9C5A032463C561423387a9648c5C7BCC5BC90"
            }, {
                "itemType": 1,
                "token": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
                "identifierOrCriteria": 0,
                "startAmount": 5000000000000000,
                "endAmount": 5000000000000000,
                "recipient": "0x8fda7f45b1427F2d4444F4c6D44D2B5d1cb46b53"
            }],
            "startTime": 0,
            "endTime": 1655574606,
            "orderType": 2,
            "zone": "0x004C00500000aD104D7DBd00e3ae0A5C00560C00",
            "zoneHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
            "salt": 89054825639822128,
            "conduitKey": "0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000",
            "totalOriginalConsiderationItems": 3,
            "counter": 0
        },
        "signature": "0x0b13752edae09a827c32381561a4709b8defa7789209d66276ef9889f9fd730867cb167c56c27b823af61db3b11810f9d103d26e225e106062ed21907525ae7b1c"
    }
plondon commented 2 years ago

This issue seems to be specific to the testnets-api, where the error returned is always

{"errors":["You cannot access body after reading from request's data stream"]}%

For mainnet, errors are coming through correctly

esteban-OpenSea commented 2 years ago

This seems to be working for me, I am running the url you all are running: https://testnets-api.opensea.io/v2/orders/rinkeby/seaport/offers

It returns a successful call.

plondon commented 2 years ago

@esteban-OpenSea thanks for the response, could you include the full curl?

douglasmoraisdev commented 2 years ago

Same error here using: https://testnets-api.opensea.io/v2/orders/rinkeby/seaport/offers

gqoew commented 2 years ago

The /orders seaport APIs endpoints are simply not working, at least for the rinkeby network. I face the same error for createSellOrder.

The error is due to a bad handling of the user request data in Opensea's API django backend. It seems pretty easy to solve this error IMO.

Also, the docs are outdated and quite confusing: endpoints differ between docs and the SDK (api/v2 in SDK and v2 in docs). They also put /ethereum in the endpoint path for the rinkeby doc examples. The order parameters format in the docs is wrong.

As a user, I expect better guidance and/or support given how seaport is currently advertised as a functional protocol.

casey-cindex commented 2 years ago

curl --request POST \ --url https://testnets-api.opensea.io/v2/orders/rinkeby/seaport/listings \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --header 'X-API-KEY: 2f6f419a083c46de9d83ce3dbe7db601' \ --data ' { "order_parameters": { "offerer": "0x45fe652136DB9a4BAC7A51B97217E16380e3C4F9", "zone": "0x9b814233894cd227f561b78cc65891aa55c62ad2", "zoneHash": "0x3000000000000000000000000000000000000000000000000000000000000000", "startTime": "1655538402", "endTime": "1656143201", "orderType": 0, "offer": [ { "itemType": 2, "token": "0xf5769f5d59e52363ac24fdd4781659430374cbb1", "identifierOrCriteria": "63", "startAmount": "1", "endAmount": "1" } ], "consideration": [ { "itemType": 0, "token": "0x0000000000000000000000000000000000000000", "identifierOrCriteria": "0", "startAmount": "1950000000000000", "endAmount": "1950000000000000", "recipient": "0x45fe652136DB9a4BAC7A51B97217E16380e3C4F9" }, { "itemType": 0, "token": "0x0000000000000000000000000000000000000000", "identifierOrCriteria": "0", "startAmount": "50000000000000", "endAmount": "50000000000000", "recipient": "0x8de9c5a032463c561423387a9648c5c7bcc5bc90" } ], "totalOriginalConsiderationItems": 2, "salt": "0x38d239ca430328b9cd02423b2942a68f", "conduitKey": "0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000", "counter": 0 }, "signature": "0x98b65e071d2c002d769d4a5a98073824a34e85232f5e094b9f8108a43c5d2b1957438185209a1e8de8a13d3de89278adfa06e3effa5890049801c21a097884ed" } '

{"errors":["You cannot access body after reading from request's data stream"]}

Benjythebee commented 2 years ago

Reproduced with mainnet API: image

      seaport = new OpenSeaPort(app.provider, {
        networkName: Network.Main,
        apiKey: process.env.OPENSEA_APIKEY,
      })

const params = ...

await seaport.createSellOrder(params)

Error appears after signing.

app.provider is window.ethereum.

opensea-js version 4.0.1 and 4.0.2

stewart-lore commented 2 years ago

I'm getting the same error on rinkeby and mainnet. I echo the same sentiment as @gqoew, the docs are wrong and confusing--fields are labeled using snake_case, but the sdk uses camelCase. The create listing doc model for parameters does not express how to put an array for considerations and offer. The sdk also works differently than the doc. I'm confused and need dev support.

mehranhydary commented 2 years ago

I'm also running into the same issues - please help!

Thanks

chenji23 commented 2 years ago

In Rinkeby, I change the URL manually to https://testnets-api.opensea.io/v2/orders/rinkeby/seaport/listings it changes to return CORS error now.

stewart-lore commented 2 years ago

Wanted to provide an update-- I got sells working with a few changes:

  1. Updating the POST listing url to https://api.opensea.io/v2/orders/ethereum/seaport/listings remove the /api path segment.
  2. Updating to latest opensea-js and seaport-js which include updated Fee payout addresses.
  3. Adding restrictedByZone: true and allowPartialFills: false to the seaport call seaport.createOrder({...}). Thanks to @plondon for this.

It's worth pointing out that I'm actually listing on chain, without a signature, from a smart contract wallet so I'm using seaport.validate() and then posting the completed order to the corrected listings api using a signature from a different EOA account.

mehranhydary commented 2 years ago

@stewart-prysm - did you wait for the seaport.validate call to complete before posting with OpenSea?

Also why did you post the order with a different signature from an EOA wallet if you can just pass in "0x" after the validate transaction is complete?

mehranhydary commented 2 years ago

@stewart-prysm - this is what I'm trying to post to the url you shared above... no luck tho (I've also validated this with the seaport.validate function)

{
    "offerer": "0x2bBe92F7478827A621a9A3E1FC9A6ccC43D1a598",
    "conduitKey": "0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000",
    "zone": "0x004C00500000aD104D7DBd00e3ae0A5C00560C00",
    "zoneHash": "0x3000000000000000000000000000000000000000000000000000000000000000",
    "startTime": "1655762569",
    "endTime": "1656367369",
    "offer": [
        {
            "itemType": 2,
            "token": "0xca21d4228cdcc68d4e23807e5e370c07577dd152",
            "identifierOrCriteria": "52742",
            "startAmount": "1",
            "endAmount": "1"
        }
    ],
    "consideration": [
        {
            "itemType": 0,
            "token": "0x0000000000000000000000000000000000000000",
            "identifierOrCriteria": "0",
            "startAmount": "36240000000000000",
            "endAmount": "36240000000000000",
            "recipient": "0x2bBe92F7478827A621a9A3E1FC9A6ccC43D1a598"
        },
        {
            "itemType": 0,
            "token": "0x0000000000000000000000000000000000000000",
            "identifierOrCriteria": "0",
            "startAmount": "1000000000000000",
            "endAmount": "1000000000000000",
            "recipient": "0x8de9c5a032463c561423387a9648c5c7bcc5bc90"
        },
        {
            "itemType": 0,
            "token": "0x0000000000000000000000000000000000000000",
            "identifierOrCriteria": "0",
            "startAmount": "2760000000000000",
            "endAmount": "2760000000000000",
            "recipient": "0xd1d1d4e36117ab794ec5d4c78cbd3a8904e691d0"
        }
    ],
    "salt": "0x74e1d1b5de785851bc55a80093c43d54",
    "totalOriginalConsiderationItems": 3,
    "orderType": 0
}
dandao2022 commented 2 years ago

I also have this problem SDK 4.0.2 can someone help me

gqoew commented 2 years ago

Wanted to provide an update-- I got sells working with a few changes:

1. Updating the POST listing url to `https://api.opensea.io/v2/orders/ethereum/seaport/listings` remove the `/api` path segment.

2. Updating to latest `opensea-js` and `seaport-js` which include updated Fee payout addresses.

3. Adding `restrictedByZone: true` and `allowPartialFills: false` to the seaport call `seaport.createOrder({...})`. Thanks to @plondon for this.

It's worth pointing out that I'm actually listing on chain, without a signature, from a smart contract wallet so I'm using seaport.validate() and then posting the completed order to the corrected listings api using a signature from a different EOA account.

hi @stewart-prysm Just to confirm, did you do the above on RINKEBY or MAINNET?

mehranhydary commented 2 years ago

@gqoew - this was done on MAINNET (see the URL he's using)

stewart-lore commented 2 years ago

@mehranhydary I've only run this on mainnet so far because rinkeby API was not returning descriptive errors for me. Yes I waited for validate to be confirmed before posting to the /listings api. I posted the order with an EOA sig because that was required on v1 of the apis for this same use case. I haven't tested passing 0x on the signature to v2. I will test that out today.

Your order JSON is incorrect. You need to pass an instance of type OrderWithCounter to the opensea api postOrder() method. It's serializable, so it's just JSON.stringify() on that type if you're not using the open sea api class. The top level object should have this scheme:

export declare type OrderWithCounter = {
    parameters: OrderComponents;
    signature: string;
};

where the object you provide is parameters and signature is EOA signature (or try passing '0x').

I also recommend using mainnet so you can get more description api error responses.

plondon commented 2 years ago

@stewart-prysm have you been able to post an offer? Or only listings?

stewart-lore commented 2 years ago

@plondon I have not tried posting an offer. I'm not planning on implementing that for a while.

mehranhydary commented 2 years ago

@stewart-prysm - thanks for these details - here's where I am now:

const res = await openseaSdk.api.postOrder(
    JSON.stringify({
        parameters: {
            offerer: '0x2bBe92F7478827A621a9A3E1FC9A6ccC43D1a598',
            conduitKey:
                '0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000',
            zone: '0x004C00500000aD104D7DBd00e3ae0A5C00560C00',
            zoneHash:
                '0x3000000000000000000000000000000000000000000000000000000000000000',
            startTime: '1655762570',
            endTime: '1656367370',
            offer: [
                {
                    itemType: 2,
                    token: '0x6be69b2a9b153737887cfcdca7781ed1511c7e36',
                    identifierOrCriteria: '4970',
                    startAmount: '1',
                    endAmount: '1',
                },
            ],
            consideration: [
                {
                    itemType: 0,
                    token: '0x0000000000000000000000000000000000000000',
                    identifierOrCriteria: '0',
                    startAmount: '945000000000000000',
                    endAmount: '945000000000000000',
                    recipient: '0x2bBe92F7478827A621a9A3E1FC9A6ccC43D1a598',
                },
                {
                    itemType: 0,
                    token: '0x0000000000000000000000000000000000000000',
                    identifierOrCriteria: '0',
                    startAmount: '25000000000000000',
                    endAmount: '25000000000000000',
                    recipient: '0x8de9c5a032463c561423387a9648c5c7bcc5bc90',
                },
                {
                    itemType: 0,
                    token: '0x0000000000000000000000000000000000000000',
                    identifierOrCriteria: '0',
                    startAmount: '30000000000000000',
                    endAmount: '30000000000000000',
                    recipient: '0xf3a3de78398aa532621b28897b445436ce6abec7',
                },
            ],
            salt: '0x8a370dc1fa5cc65bd5d705109789ad8a',
            totalOriginalConsiderationItems: 3,
            orderType: 0,
            counter: 0,
        },
        signature: '0x',
    }),
    { protocol: 'seaport', side: 'ask' }
)

This is still returning a 500 error (Error: API Error 500: Internal server error.).

plondon commented 2 years ago

@mehranhydary I think opensea api is down, I can't even make an offer from their UI (500 error). I know you are making a listing but still

mehranhydary commented 2 years ago

@plondon - ah okay - I was excited when @stewart-prysm posted that he was able to make a listing yesterday so I was feeling keen today

Thank you!!

stewart-lore commented 2 years ago

@mehranhydary openseaSdk.api.postOrder() serializes it for you, so just pass in the object

plondon commented 2 years ago

Let's keep each other posted (no pun intended). I am also trying to implement listings today. Thanks all!

mehranhydary commented 2 years ago

@plondon - yes for sure! @stewart-prysm - awesome thanks - getting a Error: API Error 400: You cannot access body after reading from request's data stream now :'( ahahaha

stewart-lore commented 2 years ago

Best of luck. I'm also implementing cancel listing on-chain today so I will keep you all updated. This is what working on bleeding edge tech feels like 🥴

mehranhydary commented 2 years ago

From OS dev discord: As programmatic orders are down currently from being made on the OpenSea Shared Storefront on the Seaport API, You can still issue programmatic orders for Shared Storefont via the wyvern endpoint.

Down horrendously ahaha

plondon commented 2 years ago

Yeah I was aware of that issue specifically for the shared storefront contract, but programmatic orders (offers at least) seem to be down for any collection.

plondon commented 2 years ago

Update: I was also able to list an asset for sale on seaport to /v2/orders/ethereum/seaport/listings. However I am calling seaport-js directly and am able to pass in the following parameters to createSellOrder:

allowPartialFills: false,
restrictedByZone: true,

full call:

const seaport = getSeaport(signer)
  const { executeAllActions } = await seaport.createOrder(
    {
      allowPartialFills: false,
      consideration: considerationFeeItems,
      endTime: expirationTime?.toString() ?? getMaxOrderExpirationTimestamp().toString(),
      offer: offerAssetItems,
      restrictedByZone: true,
      startTime: listingTime,
      zone: network === 'rinkeby' ? DEFAULT_ZONE_RINKEBY : DEFAULT_ZONE
    },
    accountAddress
  )
  const order = await executeAllActions()
  await seaport.validate([order], accountAddress)

  return order
stewart-lore commented 2 years ago

@mehranhydary I also wanted to share with you this method I created on a fork of seaport-js to help create sell orders for a smart contract wallet -- https://gist.github.com/stewart-prysm/9b5aef9409833e8c75b78e4b198ff4f4

It skips the signature check and also allows you to inject the offererAddress as the smart contract address instead of getting it from the signer.

@plondon That is similar to how I'm calling seaport. Nice work!

plondon commented 2 years ago

I opened a PR for opensea team to allow allowPartialFills and restrictedByZone flags to createBuyOrder and createSellOrder. https://github.com/ProjectOpenSea/opensea-js/pull/598

gqoew commented 2 years ago

Thank you all for the updates! It would be cool to be able to test listing orders on rinkeby though. Testing on the mainnet is counter-intuitive and risky. I will be waiting for the much needed fixes/updates/guidance from the opensea team. Once NFTNYC22 is finished hopefully 🤞

plondon commented 2 years ago

@gqoew definitely would love to see testnet fixed!

mehranhydary commented 2 years ago

Was able to post to mainnet by modifying the postOrder fn a bit:

export const postOrder = async (parameters, signature = '0x') => {
    try {

        const res = await openseaSdk.api.post(
            '/v2/orders/ethereum/seaport/listings',
            {
                parameters,
                signature,
            }
        )
        console.log(res)
        return res
    } catch (e) {
        console.error(e)
        throw e
    }
}
asghaier76 commented 2 years ago

This merged PR should have addressed removing the api prefix from the API path, though it is not included in v4.0.3 https://github.com/ProjectOpenSea/opensea-js/pull/602

vladopaets commented 2 years ago

I opened a PR for opensea team to allow allowPartialFills and restrictedByZone flags to createBuyOrder and createSellOrder. #598

So, those two options should fix 400 api error?

gqoew commented 2 years ago

I still have the error 400 You cannot access body after reading from request's data stream when trying to createSellOrder on rinkeby:

https://testnets-api.opensea.io/v2/orders/rinkeby/seaport/listings

plondon commented 2 years ago

As there still seems to be confusion (rightfully so) about the underlying issues and causes of 400 errors for mainnet and rinkeby I am going to keep a daily tab on the functionality of these function calls, apis, and services, until our OpenSea overlords implement the appropriate fixes. Let this comment mark as my daily checkin on createBuyOrder and createSellOrder

Testnet (Status: NOT WORKING)

Mainnet (Status: FUNCTIONAL)

Last updated: June 23, 2022

asghaier76 commented 2 years ago

by using the latest commit in master we get CORS error for all api calls (these requests don't include the api prefix in the api url path)

plondon commented 2 years ago

@asghaier76 maybe lets keep this thread for the 400 errors? Theres already enough confusion as is :)

mark-ht commented 2 years ago

When trying to post an order;