bennycode / coinbase-pro-node

Coinbase API written in TypeScript and covered by tests.
https://bennycode.com/coinbase-pro-node
MIT License
254 stars 62 forks source link

Is getPaymentMethods() typing broken? (PaymentMethod Interface) #862

Closed AutomationD closed 1 year ago

AutomationD commented 1 year ago

Hello, I'm a bit confused, I'm trying to use getPaymentMethods(): Promise<PaymentMethod[]>; , but the interface doesn't seem to match with api documentation: But for some reason it corresponds with a different api

I'm retrieving the data like this:

const auth = {
    apiKey: process.env.COINBASE_API_KEY || "",
    apiSecret: process.env.COINBASE_API_SECRET || "",
    passphrase: process.env.COINBASE_API_PASSPHRASE || "",
    useSandbox: false,
};

const coinbase = new CoinbasePro(auth);
const withdrawals = await coinbase.rest.transfer.getTransfers(TransferType.WITHDRAW, profile?.id)
const paymentMethods = await coinbase.rest.withdraw.getPaymentMethods()

Interface in question:

export interface PaymentMethod {
    allow_buy: boolean;
    allow_deposit: boolean;
    allow_sell: boolean;
    allow_withdraw: boolean;
    currency: string;
    id: string;
    limits: {
        buy: PaymentMethodLimit[];
        deposit: PaymentMethodLimit[];
        instant_buy: PaymentMethodLimit[];
        sell: PaymentMethodLimit[];
    };
    name: string;
    primary_buy: boolean;
    primary_sell: boolean;
    type: string;
}

Actual data received from the api:

[
  {
    "id": "xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "type": "sepa_bank_account",
    "name": "BANK (****************0000)",
    "currency": "EUR",
    "primary_buy": false,
    "primary_sell": false,
    "instant_buy": false,
    "instant_sell": false,
    "created_at": "2022-07-05T19:26:45Z",
    "updated_at": "2022-07-05T19:29:03Z",
    "resource": "payment_method",
    "resource_path": "/v2/payment-methods/xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "limits": {
      "type": "bank",
      "name": "Bank Account"
    },
    "allow_buy": false,
    "allow_sell": false,
    "allow_deposit": false,
    "allow_withdraw": true,
    "verified": true,
    "minimum_purchase_amount": {
      "amount": "0.00",
      "currency": "EUR"
    },
    "picker_data": {
      "symbol": "bank",
      "institution_name": "BANK",
      "iban": "EE300 0000 0000 0000 0000",
      "swift": "SEPA0000XXX"
    }
  }
]

Could you please let me know if I'm doing something wrong or if this method doesn't work as intended?

Thank you!

bennycode commented 1 year ago

Hi @AutomationD, did you ran the method to see what it actually returns? You could use one of the provided demo scripts to give it a try: https://github.com/bennycode/coinbase-pro-node/tree/main/src/demo

AutomationD commented 1 year ago

Hey @bennycode , thanks for your reply.

Yes, the method is executed and the data that is returned by the api is different. I've added the response to the first post. (notice the resource_path too, there's probably some redirect going on CB side)

One thing to note, I'm using server-side Coinbase Exchange api key and maybe that's what making the response to be different from the response you're expecting? I was able to find my format documented on a different api https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-payment-methods.

At this point it would be great to:

  1. Understand what's happening. Am I doing something wrong?
  2. Find a workaround for now (maybe change a base URL somewhere?)
  3. Hopefully find a solution (either documentation or updating code - maybe the solution is to mention that only Wallet Auth is supported/recommended).

Also, I wanted to thank you for such a great work!

Update.

It may be foolish, but for now I've reimplemented the interface locally as follows:

export interface PaymentMethod {
    allow_buy: boolean;
    allow_deposit: boolean;
    allow_sell: boolean;
    allow_withdraw: boolean;
    created_at: string;
    currency: string;
    id: string;
    instant_buy: boolean;
    instant_sell: boolean;
    limits: {
        type: string;
        name: string;
    };
    minimum_purchase_amount: {
        amount: string
        currency: string
    };
    name: string
    picker_data: {
        symbol: string
        institution_name: string
        iban: string
        swift: string
    }
    primary_buy: boolean
    primary_sell: boolean
    resource: string
    resource_path: string,
    type: string
    updated_at: string,
    verified: boolean
}
bennycode commented 1 year ago

Cool, would you mind sending a PR so I can approve it and get it merged in the library?

AutomationD commented 1 year ago

I don’t mind at all. I was just not sure if I’m doing things wrong. If you confirm it’s possible that the data could be different then I’m not doing anything terribly wrong.

Have you been able to replicate the same behavior as I describe here?

Thanks!

bennycode commented 1 year ago

Hi @AutomationD, I am validating now returned payloads from Coinbase using Zod. Once this PR (https://github.com/bennycode/coinbase-pro-node/pull/875) gets released, you will get only validated types. 😊 The "coinbase-pro-node" library will then throw an error if the payload returned by Coinbase doesn't match the typings defined in this library. You can then easily see what is right or wrong. Thanks for your help in finding the incosistencies of the Coinbase API.

AutomationD commented 1 year ago

ZOD FTW, thank you so much @bennycode 🙏🏻

(rant: funny enough TS requires a crutch like this)

bennycode commented 1 year ago

Well, if the Coinbase Team would provide a TypeScript SDK out-of-the-box, then we wouldn't have to build such workarounds. Let's see if your issue is fixed. I just released: https://www.npmjs.com/package/coinbase-pro-node/v/7.0.0 😃