Skip to content

fix(coinpay): read wallets whose chain field is a composite key like USDC_POL - #506

Open
clawedassistant26 wants to merge 1 commit into
profullstack:masterfrom
clawedassistant26:fix/coinpay-composite-wallet-currency
Open

fix(coinpay): read wallets whose chain field is a composite key like USDC_POL#506
clawedassistant26 wants to merge 1 commit into
profullstack:masterfrom
clawedassistant26:fix/coinpay-composite-wallet-currency

Conversation

@clawedassistant26

Copy link
Copy Markdown
Contributor

Problem

A user who has connected CoinPay with the wallet:read scope, and who has active Global Wallet Addresses on CoinPayPortal, still gets an empty wallet list from ugig:

GET /api/coinpay/wallets
{"wallets":[],"oauth_required":false,"setup_required":true}

oauth_required: false shows the OAuth grant is fine, so the setup instructions ugig returns ("connect your CoinPay account", "paste those addresses into Settings > Global Wallet Addresses") send the user round a loop they cannot escape. Invoicing is blocked because the invoice route gates on workerWallets.length === 0.

Cause

getCoinpayGlobalWalletTokens reads wallets from CoinPayPortal's OIDC /api/oauth/userinfo. That endpoint returns each wallet as:

{ "address": "0x...", "chain": "USDC_POL", "label": "...", "business_id": "..." }

One composite token, USDC_POL, names both the coin and its chain. coinToPaymentCurrency only handles a bare symbol plus a separate chain field:

  • directCurrency looks at currency, id and code, none of which are present, so it is empty.
  • symbol falls through to coin.chain and becomes "USDC_POL", which matches none of the BTC / ETH / USDT / USDC branches.
  • The function returns null, so normalizeGlobalWallets hits if (!currency || !address) continue and drops every wallet.

The same shape appears in the cryptocurrency column of merchant_wallets and business_wallets, so anything reading those rows directly is affected too. This became visible to more users after coinpayportal#197, which made userinfo return business wallets as well as account ones.

Fix

  • compositeCurrencyKey resolves an identifier that is already a supported currency key containing an underscore (usdc_pol, usdt_pol, usdc_eth, ...). A composite match wins over a bare symbol found elsewhere on the record, because it carries the chain too.
  • The symbol lookup now also considers cryptocurrency, and splits a symbol that carries its own chain suffix, so USDC-POLYGON and USDT_ETHEREUM resolve through the existing branches.
  • The { symbol: "USDT", chain: "POL" } shape returned by /api/get-tokens is unchanged: a bare symbol splits to itself with no chain parts.

Tests

Added to src/lib/coinpayportal.test.ts:

  • coinToPaymentCurrency resolves composite tokens, still resolves the bare symbol plus chain shape, splits a suffixed symbol, and returns null when nothing identifies the coin.
  • getCoinpayGlobalWalletTokens normalizes a real userinfo payload into ["usdc_pol", "usdt_pol"], and still drops a wallet whose address fails validation for its chain.

The three new failing assertions reproduce the bug on master before the change (expected [] to deeply equal [ 'usdc_pol', 'usdt_pol' ]).

Full suite after the change: 1803 tests across 197 files pass, and tsc --noEmit is clean.

CoinPayPortal's OIDC userinfo `wallets` claim returns one composite token
that names both the coin and its chain:

  { address: "0x...", chain: "USDC_POL", label, business_id }

coinToPaymentCurrency only understood a bare symbol ("USDC") plus a
separate chain ("POL"). It read "USDC_POL" into the symbol slot, matched
no branch and returned null, so normalizeGlobalWallets dropped every
wallet. Connected users saw wallets: [] with oauth_required: false and
could never send an invoice, even with active global wallet addresses on
CoinPay.

Resolve a composite identifier first, and split a symbol that carries its
own chain suffix ("USDC-POLYGON") so it still lands on the right branch.
The bare symbol plus separate chain shape from /api/get-tokens is
unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant