@b3dotfun/sdk 0.1.70-alpha.18 → 0.1.70-alpha.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/README.md +3 -3
  2. package/dist/cjs/anyspend/constants/rpc.d.ts +1 -0
  3. package/dist/cjs/anyspend/constants/rpc.js +3 -1
  4. package/dist/cjs/anyspend/react/components/AnySpendDeposit.d.ts +1 -3
  5. package/dist/cjs/anyspend/react/components/AnySpendDeposit.js +14 -12
  6. package/dist/cjs/anyspend/react/components/AnySpendStakeB3.js +32 -13
  7. package/dist/cjs/anyspend/react/components/AnySpendStakeB3ExactIn.js +32 -10
  8. package/dist/cjs/anyspend/react/components/checkout/CryptoPayPanel.js +16 -8
  9. package/dist/cjs/anyspend/react/components/common/TokenBalance.js +4 -5
  10. package/dist/cjs/anyspend/react/hooks/useSigMint.d.ts +1 -1
  11. package/dist/cjs/anyspend/utils/chain.d.ts +45 -0
  12. package/dist/cjs/anyspend/utils/chain.js +51 -2
  13. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.d.ts +1 -2
  14. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.js +2 -2
  15. package/dist/cjs/global-account/react/components/B3Provider/RelayKitProviderWrapper.d.ts +1 -2
  16. package/dist/cjs/global-account/react/components/B3Provider/RelayKitProviderWrapper.js +4 -5
  17. package/dist/cjs/global-account/react/components/ManageAccount/ContentTokens.js +23 -15
  18. package/dist/cjs/global-account/react/components/ManageAccount/NFTContent.js +2 -2
  19. package/dist/cjs/global-account/react/components/ManageAccount/ProfileSection.js +8 -6
  20. package/dist/cjs/global-account/react/components/ManageAccount/TokenContent.js +17 -8
  21. package/dist/cjs/global-account/react/components/Send/Send.js +15 -11
  22. package/dist/cjs/global-account/react/hooks/index.d.ts +2 -2
  23. package/dist/cjs/global-account/react/hooks/index.js +7 -8
  24. package/dist/cjs/global-account/react/hooks/useAuth.d.ts +2 -1
  25. package/dist/cjs/global-account/react/hooks/useAuth.js +1 -0
  26. package/dist/cjs/global-account/react/hooks/useAuthentication.d.ts +2 -1
  27. package/dist/cjs/global-account/react/hooks/useAuthentication.js +1 -0
  28. package/dist/cjs/global-account/react/hooks/useFirstEOA.d.ts +4 -7666
  29. package/dist/cjs/global-account/react/hooks/useFirstEOA.js +1 -0
  30. package/dist/cjs/global-account/react/hooks/usePortfolioBalance.d.ts +15 -0
  31. package/dist/cjs/global-account/react/hooks/usePortfolioBalance.js +76 -0
  32. package/dist/cjs/global-account/react/hooks/usePortfolioCollectibles.d.ts +12 -0
  33. package/dist/cjs/global-account/react/hooks/usePortfolioCollectibles.js +178 -0
  34. package/dist/cjs/global-account/react/stores/useModalStore.d.ts +0 -2
  35. package/dist/cjs/global-account/react/utils/createWagmiConfig.d.ts +2 -2
  36. package/dist/cjs/shared/constants/chains/b3Chain.d.ts +24 -0
  37. package/dist/cjs/shared/constants/chains/supported.d.ts +4 -4
  38. package/dist/cjs/shared/constants/index.d.ts +4 -0
  39. package/dist/cjs/shared/utils/zerionPositions.d.ts +96 -0
  40. package/dist/cjs/shared/utils/zerionPositions.js +186 -0
  41. package/dist/cjs/wallet/utils/createWalletConfig.d.ts +2 -2
  42. package/dist/esm/anyspend/constants/rpc.d.ts +1 -0
  43. package/dist/esm/anyspend/constants/rpc.js +2 -0
  44. package/dist/esm/anyspend/react/components/AnySpendDeposit.d.ts +1 -3
  45. package/dist/esm/anyspend/react/components/AnySpendDeposit.js +15 -13
  46. package/dist/esm/anyspend/react/components/AnySpendStakeB3.js +33 -14
  47. package/dist/esm/anyspend/react/components/AnySpendStakeB3ExactIn.js +33 -11
  48. package/dist/esm/anyspend/react/components/checkout/CryptoPayPanel.js +18 -10
  49. package/dist/esm/anyspend/react/components/common/TokenBalance.js +6 -7
  50. package/dist/esm/anyspend/react/hooks/useSigMint.d.ts +1 -1
  51. package/dist/esm/anyspend/utils/chain.d.ts +45 -0
  52. package/dist/esm/anyspend/utils/chain.js +50 -3
  53. package/dist/esm/global-account/react/components/B3Provider/B3Provider.d.ts +1 -2
  54. package/dist/esm/global-account/react/components/B3Provider/B3Provider.js +2 -2
  55. package/dist/esm/global-account/react/components/B3Provider/RelayKitProviderWrapper.d.ts +1 -2
  56. package/dist/esm/global-account/react/components/B3Provider/RelayKitProviderWrapper.js +4 -5
  57. package/dist/esm/global-account/react/components/ManageAccount/ContentTokens.js +24 -16
  58. package/dist/esm/global-account/react/components/ManageAccount/NFTContent.js +3 -3
  59. package/dist/esm/global-account/react/components/ManageAccount/ProfileSection.js +9 -7
  60. package/dist/esm/global-account/react/components/ManageAccount/TokenContent.js +18 -9
  61. package/dist/esm/global-account/react/components/Send/Send.js +16 -12
  62. package/dist/esm/global-account/react/hooks/index.d.ts +2 -2
  63. package/dist/esm/global-account/react/hooks/index.js +2 -2
  64. package/dist/esm/global-account/react/hooks/useAuth.d.ts +2 -1
  65. package/dist/esm/global-account/react/hooks/useAuth.js +1 -0
  66. package/dist/esm/global-account/react/hooks/useAuthentication.d.ts +2 -1
  67. package/dist/esm/global-account/react/hooks/useAuthentication.js +1 -0
  68. package/dist/esm/global-account/react/hooks/useFirstEOA.d.ts +4 -7666
  69. package/dist/esm/global-account/react/hooks/useFirstEOA.js +1 -0
  70. package/dist/esm/global-account/react/hooks/usePortfolioBalance.d.ts +15 -0
  71. package/dist/esm/global-account/react/hooks/usePortfolioBalance.js +72 -0
  72. package/dist/esm/global-account/react/hooks/usePortfolioCollectibles.d.ts +12 -0
  73. package/dist/esm/global-account/react/hooks/usePortfolioCollectibles.js +175 -0
  74. package/dist/esm/global-account/react/stores/useModalStore.d.ts +0 -2
  75. package/dist/esm/global-account/react/utils/createWagmiConfig.d.ts +2 -2
  76. package/dist/esm/shared/constants/chains/b3Chain.d.ts +24 -0
  77. package/dist/esm/shared/constants/chains/supported.d.ts +4 -4
  78. package/dist/esm/shared/constants/index.d.ts +4 -0
  79. package/dist/esm/shared/utils/zerionPositions.d.ts +96 -0
  80. package/dist/esm/shared/utils/zerionPositions.js +178 -0
  81. package/dist/esm/wallet/utils/createWalletConfig.d.ts +2 -2
  82. package/dist/types/anyspend/constants/rpc.d.ts +1 -0
  83. package/dist/types/anyspend/react/components/AnySpendDeposit.d.ts +1 -3
  84. package/dist/types/anyspend/react/hooks/useSigMint.d.ts +1 -1
  85. package/dist/types/anyspend/utils/chain.d.ts +45 -0
  86. package/dist/types/global-account/react/components/B3Provider/B3Provider.d.ts +1 -2
  87. package/dist/types/global-account/react/components/B3Provider/RelayKitProviderWrapper.d.ts +1 -2
  88. package/dist/types/global-account/react/hooks/index.d.ts +2 -2
  89. package/dist/types/global-account/react/hooks/useAuth.d.ts +2 -1
  90. package/dist/types/global-account/react/hooks/useAuthentication.d.ts +2 -1
  91. package/dist/types/global-account/react/hooks/useFirstEOA.d.ts +4 -7666
  92. package/dist/types/global-account/react/hooks/usePortfolioBalance.d.ts +15 -0
  93. package/dist/types/global-account/react/hooks/usePortfolioCollectibles.d.ts +12 -0
  94. package/dist/types/global-account/react/stores/useModalStore.d.ts +0 -2
  95. package/dist/types/global-account/react/utils/createWagmiConfig.d.ts +2 -2
  96. package/dist/types/shared/constants/chains/b3Chain.d.ts +24 -0
  97. package/dist/types/shared/constants/chains/supported.d.ts +4 -4
  98. package/dist/types/shared/constants/index.d.ts +4 -0
  99. package/dist/types/shared/utils/zerionPositions.d.ts +96 -0
  100. package/dist/types/wallet/utils/createWalletConfig.d.ts +2 -2
  101. package/node_modules/@b3/chain-registry/chains.json +29 -1
  102. package/node_modules/@b3/chain-registry/package.json +18 -2
  103. package/package.json +2 -2
  104. package/src/anyspend/README.md +2 -2
  105. package/src/anyspend/constants/rpc.ts +2 -0
  106. package/src/anyspend/docs/components.md +6 -6
  107. package/src/anyspend/docs/contributing.md +1 -1
  108. package/src/anyspend/docs/hooks.md +3 -3
  109. package/src/anyspend/docs/installation.md +2 -2
  110. package/src/anyspend/react/components/AnySpendDeposit.tsx +26 -19
  111. package/src/anyspend/react/components/AnySpendStakeB3.tsx +55 -14
  112. package/src/anyspend/react/components/AnySpendStakeB3ExactIn.tsx +55 -11
  113. package/src/anyspend/react/components/__tests__/QRDeposit.test.tsx +3 -4
  114. package/src/anyspend/react/components/checkout/CryptoPayPanel.tsx +25 -12
  115. package/src/anyspend/react/components/common/TokenBalance.tsx +10 -7
  116. package/src/anyspend/utils/__tests__/deprecatedChains.test.ts +44 -0
  117. package/src/anyspend/utils/__tests__/toRegistryChainId.test.ts +17 -0
  118. package/src/anyspend/utils/chain.ts +53 -2
  119. package/src/global-account/react/components/B3Provider/B3Provider.tsx +1 -3
  120. package/src/global-account/react/components/B3Provider/RelayKitProviderWrapper.tsx +4 -11
  121. package/src/global-account/react/components/ManageAccount/ContentTokens.tsx +50 -21
  122. package/src/global-account/react/components/ManageAccount/NFTContent.tsx +5 -3
  123. package/src/global-account/react/components/ManageAccount/ProfileSection.tsx +10 -6
  124. package/src/global-account/react/components/ManageAccount/TokenContent.tsx +22 -9
  125. package/src/global-account/react/components/Send/Send.tsx +39 -15
  126. package/src/global-account/react/hooks/index.ts +2 -2
  127. package/src/global-account/react/hooks/useAuth.ts +3 -2
  128. package/src/global-account/react/hooks/useAuthentication.ts +3 -2
  129. package/src/global-account/react/hooks/useFirstEOA.tsx +9 -2
  130. package/src/global-account/react/hooks/usePortfolioBalance.ts +89 -0
  131. package/src/global-account/react/hooks/usePortfolioCollectibles.ts +212 -0
  132. package/src/global-account/react/stores/useModalStore.ts +0 -2
  133. package/src/shared/constants/index.ts +8 -0
  134. package/src/shared/utils/__tests__/zerionPositions.test.ts +226 -0
  135. package/src/shared/utils/zerionPositions.ts +244 -0
  136. package/dist/cjs/global-account/react/hooks/useSimBalance.d.ts +0 -59
  137. package/dist/cjs/global-account/react/hooks/useSimBalance.js +0 -98
  138. package/dist/cjs/global-account/react/hooks/useSimCollectibles.d.ts +0 -45
  139. package/dist/cjs/global-account/react/hooks/useSimCollectibles.js +0 -190
  140. package/dist/cjs/global-account/react/utils/simdune.d.ts +0 -7
  141. package/dist/cjs/global-account/react/utils/simdune.js +0 -21
  142. package/dist/esm/global-account/react/hooks/useSimBalance.d.ts +0 -59
  143. package/dist/esm/global-account/react/hooks/useSimBalance.js +0 -93
  144. package/dist/esm/global-account/react/hooks/useSimCollectibles.d.ts +0 -45
  145. package/dist/esm/global-account/react/hooks/useSimCollectibles.js +0 -187
  146. package/dist/esm/global-account/react/utils/simdune.d.ts +0 -7
  147. package/dist/esm/global-account/react/utils/simdune.js +0 -17
  148. package/dist/types/global-account/react/hooks/useSimBalance.d.ts +0 -59
  149. package/dist/types/global-account/react/hooks/useSimCollectibles.d.ts +0 -45
  150. package/dist/types/global-account/react/utils/simdune.d.ts +0 -7
  151. package/node_modules/@b3/chain-registry/src/index.ts +0 -169
  152. package/node_modules/@b3/chain-registry/tsconfig.json +0 -16
  153. package/src/global-account/react/hooks/useSimBalance.ts +0 -164
  154. package/src/global-account/react/hooks/useSimCollectibles.ts +0 -238
  155. package/src/global-account/react/utils/simdune.ts +0 -20
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Canonical browser-side translation of Zerion wallet positions into B3 balance rows.
3
+ *
4
+ * This lives in the published SDK because every browser consumer needs it — the apps in this repo
5
+ * and the sites that install `@b3dotfun/sdk` from npm — and the in-repo Zerion client is a private
6
+ * workspace package that a published package cannot depend on. Backend services keep their own
7
+ * translation: pulling a browser SDK into a Node service to share one function is a worse trade
8
+ * than the second copy.
9
+ *
10
+ * Only the HTTP layer differs between callers. The rules below — which row counts as the chain's
11
+ * native coin, and which rows have no usable identity — must not be re-derived anywhere else.
12
+ */
13
+
14
+ /** Address B3 uses for a chain's native coin on EVM. Matches NATIVE_TOKEN_ADDRESSES. */
15
+ export const EVM_NATIVE_TOKEN_ADDRESS = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
16
+ export const SOLANA_NATIVE_TOKEN_ADDRESS = "So11111111111111111111111111111111111111112";
17
+ export const SOLANA_ZERION_SLUG = "solana";
18
+ /** What Zerion's `quantity.int` is: a base-10 integer, unbounded in length. */
19
+ const DECIMAL_INTEGER_PATTERN = /^\d+$/;
20
+ /** Solana's chain id as the chain registry defines it — the id every balance row is keyed by. */
21
+ export const SOLANA_CHAIN_ID = 7565164;
22
+
23
+ /**
24
+ * Zerion chain slug → numeric chain id. Slugs are Zerion's own vocabulary and do not always match
25
+ * the chain's common name — Gnosis is `xdai`, Metis is `metis-andromeda` — so an entry invented
26
+ * from the chain name silently drops every position on that chain, because the adapter skips any
27
+ * slug it cannot map. Every entry here is taken from Zerion's `GET /v1/chains/`.
28
+ */
29
+ const ZERION_CHAIN_IDS: Readonly<Record<string, number>> = {
30
+ ethereum: 1,
31
+ optimism: 10,
32
+ "binance-smart-chain": 56,
33
+ xdai: 100,
34
+ unichain: 130,
35
+ polygon: 137,
36
+ sonic: 146,
37
+ fantom: 250,
38
+ "zksync-era": 324,
39
+ world: 480,
40
+ hyperevm: 999,
41
+ "metis-andromeda": 1088,
42
+ "polygon-zkevm": 1101,
43
+ soneium: 1868,
44
+ ronin: 2020,
45
+ abstract: 2741,
46
+ robinhood: 4663,
47
+ mantle: 5000,
48
+ base: 8453,
49
+ mode: 34443,
50
+ arbitrum: 42161,
51
+ celo: 42220,
52
+ avalanche: 43114,
53
+ linea: 59144,
54
+ berachain: 80094,
55
+ blast: 81457,
56
+ taiko: 167000,
57
+ scroll: 534352,
58
+ zora: 7777777,
59
+ degen: 666666666,
60
+ aurora: 1313161554,
61
+ [SOLANA_ZERION_SLUG]: SOLANA_CHAIN_ID,
62
+ };
63
+
64
+ // Maps rather than objects: a slug arrives straight off the wire, and an object lookup resolves an
65
+ // inherited key like `constructor` or `toString` to something truthy instead of reporting the chain
66
+ // as unknown — which would carry a row past the `=== undefined` guard with a function as its id.
67
+ const CHAIN_ID_BY_ZERION_SLUG: ReadonlyMap<string, number> = new Map(Object.entries(ZERION_CHAIN_IDS));
68
+
69
+ const ZERION_SLUG_BY_CHAIN_ID: ReadonlyMap<number, string> = new Map(
70
+ Object.entries(ZERION_CHAIN_IDS).map(([slug, id]) => [id, slug]),
71
+ );
72
+
73
+ export function zerionSlugToChainId(slug: string): number | undefined {
74
+ return CHAIN_ID_BY_ZERION_SLUG.get(slug);
75
+ }
76
+
77
+ export function chainIdToZerionSlug(chainId: number): string | undefined {
78
+ return ZERION_SLUG_BY_CHAIN_ID.get(chainId);
79
+ }
80
+
81
+ export interface ZerionPositionQuantity {
82
+ int?: string;
83
+ decimals?: number;
84
+ }
85
+
86
+ export interface ZerionPositionImplementation {
87
+ chain_id?: string;
88
+ address?: string | null;
89
+ decimals?: number;
90
+ }
91
+
92
+ export interface ZerionPositionFungibleInfo {
93
+ name?: string;
94
+ symbol?: string;
95
+ icon?: { url?: string } | null;
96
+ implementations?: ZerionPositionImplementation[];
97
+ }
98
+
99
+ export interface ZerionPositionLike {
100
+ id?: string;
101
+ attributes?: {
102
+ quantity?: ZerionPositionQuantity;
103
+ value?: number | null;
104
+ price?: number | null;
105
+ fungible_info?: ZerionPositionFungibleInfo;
106
+ flags?: { displayable?: boolean; is_trash?: boolean };
107
+ };
108
+ relationships?: { chain?: { data?: { id?: string } } };
109
+ }
110
+
111
+ /** One spendable holding. `amount` is the raw integer; pair it with `decimals` to display. */
112
+ export interface B3TokenBalance {
113
+ chain: string;
114
+ chain_id: number;
115
+ address: string;
116
+ amount: string;
117
+ symbol: string;
118
+ decimals: number;
119
+ /**
120
+ * Whether `address` is the native-coin sentinel rather than a real contract. Callers deciding
121
+ * between a value-bearing send and an ERC-20 `transfer` MUST branch on this, never on the
122
+ * sentinel string: getting it backwards spends gas and moves nothing.
123
+ */
124
+ is_native: boolean;
125
+ name?: string;
126
+ price_usd?: number;
127
+ value_usd?: number;
128
+ token_metadata?: { logo: string };
129
+ }
130
+
131
+ /**
132
+ * Zerion encodes a position's asset in the first hyphen-delimited segment of its resource `id`
133
+ * (`<assetRef>-<chainSlug>-<positionType>-…`). A chain's native coin uses the literal `base`
134
+ * (`base-polygon-asset-asset`); ERC-20s use the contract address
135
+ * (`0x1dd17…-ethereum-asset-asset`).
136
+ *
137
+ * This is the only reliable native signal. A falsy per-chain `implementation.address` looks
138
+ * equivalent and is not: Zerion reports Polygon's native coin at its `0x…1010` system contract and
139
+ * Celo's at a real ERC-20 address, while Polygon simultaneously carries a non-native fungible with
140
+ * the same `POL` symbol. Keying on the address shape misclassifies both.
141
+ */
142
+ function isNativePosition(id: string | undefined, impl: ZerionPositionImplementation | undefined): boolean {
143
+ if (id?.startsWith("base-") === true) return true;
144
+ // Second signal, for the chains that spell native as an absent address. It requires the
145
+ // implementation to EXIST: a fungible with no entry for this chain tells us nothing about what
146
+ // the row is, and calling that native would hand a value-bearing send an amount we cannot name.
147
+ return impl !== undefined && !impl.address;
148
+ }
149
+
150
+ export function nativeTokenAddressForChain(slug: string): string {
151
+ return slug === SOLANA_ZERION_SLUG ? SOLANA_NATIVE_TOKEN_ADDRESS : EVM_NATIVE_TOKEN_ADDRESS;
152
+ }
153
+
154
+ /**
155
+ * Every spelling of "the chain's own coin" a caller might hold.
156
+ *
157
+ * A token record's address depends on where it came from — a quote provider, a token list, a URL
158
+ * parameter — and each source names the native coin differently. Matching a balance row against any
159
+ * single one of these silently fails for the others.
160
+ */
161
+ const NATIVE_TOKEN_MARKERS: ReadonlySet<string> = new Set([
162
+ "native",
163
+ "0x0000000000000000000000000000000000000000",
164
+ EVM_NATIVE_TOKEN_ADDRESS,
165
+ SOLANA_NATIVE_TOKEN_ADDRESS.toLowerCase(),
166
+ "11111111111111111111111111111111",
167
+ ]);
168
+
169
+ /**
170
+ * Whether `balance` is the token identified by `tokenAddress`.
171
+ *
172
+ * Native coins are matched on the row's `is_native` flag rather than its printed address, because
173
+ * the caller and the adapter rarely spell the native coin the same way.
174
+ */
175
+ export function balanceMatchesToken(balance: B3TokenBalance, tokenAddress: string): boolean {
176
+ const wanted = tokenAddress.toLowerCase();
177
+ if (NATIVE_TOKEN_MARKERS.has(wanted)) return balance.is_native;
178
+ // Case-insensitive only for hex contract addresses. Solana mints are base58, where case is
179
+ // significant — lowercasing them would let two distinct mints compare equal.
180
+ if (balance.chain === SOLANA_ZERION_SLUG) return balance.address === tokenAddress;
181
+ return balance.address.toLowerCase() === wanted;
182
+ }
183
+
184
+ /**
185
+ * Adapt raw Zerion positions into balance rows, dropping any row we cannot describe honestly.
186
+ *
187
+ * A row is dropped when its chain slug is absent or unmapped, or when neither the quantity nor the
188
+ * chain implementation carries decimals — an amount rendered against a guessed scale is a wrong
189
+ * number presented as a real one, which is worse for the reader than a missing row.
190
+ *
191
+ * @param slugToChainId overrides slug resolution; return undefined to skip a chain entirely.
192
+ */
193
+ export function adaptZerionPositions(
194
+ positions: ZerionPositionLike[],
195
+ slugToChainId: (slug: string) => number | undefined = zerionSlugToChainId,
196
+ ): B3TokenBalance[] {
197
+ const out: B3TokenBalance[] = [];
198
+
199
+ for (const position of positions) {
200
+ const attributes = position.attributes ?? {};
201
+ const flags = attributes.flags;
202
+ if (flags && (flags.displayable === false || flags.is_trash === true)) continue;
203
+
204
+ const slug = position.relationships?.chain?.data?.id;
205
+ if (!slug) continue;
206
+
207
+ const chainId = slugToChainId(slug);
208
+ if (chainId === undefined) continue;
209
+
210
+ const fungibleInfo = attributes.fungible_info ?? {};
211
+ const implementation = (fungibleInfo.implementations ?? []).find(entry => entry.chain_id === slug);
212
+
213
+ const decimals = attributes.quantity?.decimals ?? implementation?.decimals;
214
+ if (decimals === undefined) continue;
215
+
216
+ const isNative = isNativePosition(position.id, implementation);
217
+ // A non-native row with no contract address has no on-chain identity — drop it rather than
218
+ // render a holding nothing can name.
219
+ const address = isNative ? nativeTokenAddressForChain(slug) : implementation?.address;
220
+ if (!address) continue;
221
+
222
+ // A quantity we cannot read is not a zero balance. Must be the base-10 integer `quantity.int`
223
+ // is: `null`, `""`, and any other unusable string all format to NaN, which callers coerce back
224
+ // to 0 and show as "holds none". `"0"` matches, so a real zero balance still comes through.
225
+ const amount = attributes.quantity?.int;
226
+ if (amount === undefined || !DECIMAL_INTEGER_PATTERN.test(amount)) continue;
227
+
228
+ out.push({
229
+ chain: slug,
230
+ chain_id: chainId,
231
+ address,
232
+ amount,
233
+ symbol: fungibleInfo.symbol ?? "",
234
+ decimals,
235
+ is_native: isNative,
236
+ name: fungibleInfo.name,
237
+ price_usd: attributes.price ?? undefined,
238
+ value_usd: attributes.value ?? undefined,
239
+ token_metadata: fungibleInfo.icon?.url ? { logo: fungibleInfo.icon.url } : undefined,
240
+ });
241
+ }
242
+
243
+ return out;
244
+ }
@@ -1,59 +0,0 @@
1
- export interface SimTokenMetadata {
2
- logo?: string;
3
- }
4
- export interface SimBalanceItem {
5
- chain: string;
6
- chain_id: number;
7
- address: string;
8
- amount: string;
9
- symbol: string;
10
- decimals: number;
11
- price_usd?: number;
12
- value_usd?: number;
13
- name?: string;
14
- token_metadata?: SimTokenMetadata;
15
- pool_size?: number;
16
- low_liquidity?: boolean;
17
- }
18
- export interface SimBalanceResponse {
19
- request_time: string;
20
- response_time: string;
21
- wallet_address: string;
22
- balances: SimBalanceItem[];
23
- }
24
- export interface SvmBalanceItem {
25
- chain: string;
26
- address: string;
27
- amount: string;
28
- balance: string;
29
- raw_balance: string;
30
- value_usd?: number;
31
- program_id: string | null;
32
- decimals: number;
33
- total_supply: string;
34
- metadata_address?: string;
35
- name?: string;
36
- symbol: string;
37
- uri?: string | null;
38
- price_usd?: number;
39
- liquidity_usd?: number;
40
- pool_type?: string | null;
41
- pool_address?: string | null;
42
- mint_authority?: string | null;
43
- }
44
- export interface SvmBalanceResponse {
45
- processing_time_ms?: number;
46
- wallet_address: string;
47
- next_offset?: string;
48
- balances_count?: number;
49
- balances: SvmBalanceItem[];
50
- }
51
- export declare function useSimBalance(address?: string, chainIdsParam?: number[]): import("@tanstack/react-query").UseQueryResult<SimBalanceResponse, Error>;
52
- export declare function useSimSvmBalance(address?: string, chains?: ("solana" | "eclipse")[], limit?: number): import("@tanstack/react-query").UseQueryResult<SvmBalanceResponse, Error>;
53
- /**
54
- * Hook to fetch a single token balance for a wallet.
55
- * @param walletAddress - The wallet address to fetch balance for
56
- * @param tokenAddress - The token contract address, or "native" for native token (ETH, etc.)
57
- * @param chainId - Chain ID to query (defaults to 1 for Ethereum mainnet)
58
- */
59
- export declare function useSimTokenBalance(walletAddress?: string, tokenAddress?: string, chainId?: number): import("@tanstack/react-query").UseQueryResult<SimBalanceResponse, Error>;
@@ -1,98 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useSimBalance = useSimBalance;
4
- exports.useSimSvmBalance = useSimSvmBalance;
5
- exports.useSimTokenBalance = useSimTokenBalance;
6
- const react_query_1 = require("@tanstack/react-query");
7
- const simdune_1 = require("../utils/simdune");
8
- async function fetchSimBalance(address, chainIdsParam) {
9
- if (!address)
10
- throw new Error("Address is required");
11
- const chainIds = chainIdsParam.length === 0 ? "mainnet" : chainIdsParam.join(",");
12
- const queryParams = new URLSearchParams();
13
- queryParams.append("metadata", "logo");
14
- queryParams.append("chain_ids", chainIds);
15
- queryParams.append("exclude_spam_tokens", "true");
16
- const url = (0, simdune_1.buildSimduneUrl)(`/v1/evm/balances/${address}`, queryParams);
17
- const response = await fetch(url);
18
- if (!response.ok) {
19
- throw new Error(`Failed to fetch balance: ${response.statusText}`);
20
- }
21
- const balanceData = await response.json();
22
- return balanceData;
23
- }
24
- async function fetchSimTokenBalance(walletAddress, tokenAddress, chainId) {
25
- if (!walletAddress)
26
- throw new Error("Wallet address is required");
27
- if (!tokenAddress)
28
- throw new Error("Token address is required");
29
- if (!chainId)
30
- throw new Error("Chain ID is required");
31
- const queryParams = new URLSearchParams();
32
- queryParams.append("chain_ids", chainId.toString());
33
- const url = (0, simdune_1.buildSimduneUrl)(`/v1/evm/balances/${walletAddress}/token/${tokenAddress}`, queryParams);
34
- const response = await fetch(url);
35
- if (!response.ok) {
36
- throw new Error(`Failed to fetch token balance: ${response.statusText}`);
37
- }
38
- const balanceData = await response.json();
39
- return balanceData;
40
- }
41
- async function fetchSimSvmBalance(address, chains, limit) {
42
- if (!address)
43
- throw new Error("Address is required");
44
- const queryParams = new URLSearchParams();
45
- if (chains && chains.length > 0) {
46
- queryParams.append("chains", chains.join(","));
47
- }
48
- if (limit) {
49
- queryParams.append("limit", limit.toString());
50
- }
51
- const url = (0, simdune_1.buildSimduneUrl)(`/beta/svm/balances/${address}`, queryParams.toString() ? queryParams : undefined);
52
- const response = await fetch(url);
53
- if (!response.ok) {
54
- throw new Error(`Failed to fetch SVM balance: ${response.statusText}`);
55
- }
56
- const balanceData = await response.json();
57
- return balanceData;
58
- }
59
- function useSimBalance(address, chainIdsParam) {
60
- return (0, react_query_1.useQuery)({
61
- queryKey: ["simBalance", address, chainIdsParam],
62
- queryFn: () => {
63
- if (!address)
64
- throw new Error("Address is required");
65
- return fetchSimBalance(address, chainIdsParam || []);
66
- },
67
- enabled: Boolean(address),
68
- });
69
- }
70
- function useSimSvmBalance(address, chains, limit) {
71
- return (0, react_query_1.useQuery)({
72
- queryKey: ["svmBalance", address, chains, limit],
73
- queryFn: () => {
74
- if (!address)
75
- throw new Error("Address is required");
76
- return fetchSimSvmBalance(address, chains, limit);
77
- },
78
- enabled: Boolean(address),
79
- });
80
- }
81
- /**
82
- * Hook to fetch a single token balance for a wallet.
83
- * @param walletAddress - The wallet address to fetch balance for
84
- * @param tokenAddress - The token contract address, or "native" for native token (ETH, etc.)
85
- * @param chainId - Chain ID to query (defaults to 1 for Ethereum mainnet)
86
- */
87
- function useSimTokenBalance(walletAddress, tokenAddress, chainId) {
88
- return (0, react_query_1.useQuery)({
89
- queryKey: ["simTokenBalance", walletAddress, tokenAddress, chainId],
90
- queryFn: () => {
91
- if (!walletAddress || !tokenAddress || !chainId) {
92
- throw new Error("Missing required parameters");
93
- }
94
- return fetchSimTokenBalance(walletAddress, tokenAddress, chainId);
95
- },
96
- enabled: Boolean(walletAddress) && Boolean(tokenAddress),
97
- });
98
- }
@@ -1,45 +0,0 @@
1
- import type { SimpleHashNFTResponse } from "../../../global-account/types/simplehash.types";
2
- export interface SimCollectibleMetadata {
3
- uri: string;
4
- attributes?: Array<{
5
- trait_type: string;
6
- value: string;
7
- display_type?: string | null;
8
- }>;
9
- }
10
- export interface SimCollectibleEntry {
11
- contract_address: string;
12
- token_standard: "ERC721" | "ERC1155";
13
- token_id: string;
14
- chain: string;
15
- chain_id: number;
16
- name?: string;
17
- description?: string;
18
- symbol?: string;
19
- image_url?: string;
20
- last_sale_price?: string;
21
- metadata?: SimCollectibleMetadata;
22
- is_spam?: boolean;
23
- spam_score?: number;
24
- explanations?: string[];
25
- balance?: string;
26
- last_acquired?: string;
27
- }
28
- export interface SimCollectiblesResponse {
29
- address: string;
30
- entries: SimCollectibleEntry[];
31
- next_offset?: string;
32
- request_time: string;
33
- response_time: string;
34
- }
35
- /**
36
- * Hook to fetch NFT collectibles from Simdune API.
37
- * Returns data in SimpleHash format for compatibility with AccountAssets component.
38
- * @param address - Wallet address to fetch collectibles for
39
- * @param chainIdsParam - Optional array of chain IDs to filter by
40
- * @param options - Optional parameters (limit, filterSpam)
41
- */
42
- export declare function useSimCollectibles(address?: string, chainIdsParam?: number[], options?: {
43
- limit?: number;
44
- filterSpam?: boolean;
45
- }): import("@tanstack/react-query").UseQueryResult<SimpleHashNFTResponse, Error>;
@@ -1,190 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useSimCollectibles = useSimCollectibles;
4
- const react_query_1 = require("@tanstack/react-query");
5
- const simdune_1 = require("../utils/simdune");
6
- /**
7
- * Safely parse a balance string to a number, capping at MAX_SAFE_INTEGER
8
- * to prevent overflow issues with large ERC1155 balances.
9
- */
10
- function safeParseBalance(balance) {
11
- if (!balance)
12
- return 1;
13
- const parsed = parseInt(balance, 10);
14
- if (Number.isNaN(parsed))
15
- return 1;
16
- return Math.min(parsed, Number.MAX_SAFE_INTEGER);
17
- }
18
- async function fetchSimCollectibles(address, chainIdsParam, options) {
19
- if (!address)
20
- throw new Error("Address is required");
21
- const queryParams = new URLSearchParams();
22
- if (chainIdsParam && chainIdsParam.length > 0) {
23
- queryParams.append("chain_ids", chainIdsParam.join(","));
24
- }
25
- if (options?.limit) {
26
- queryParams.append("limit", options.limit.toString());
27
- }
28
- if (options?.filterSpam !== undefined) {
29
- queryParams.append("filter_spam", options.filterSpam.toString());
30
- }
31
- const url = (0, simdune_1.buildSimduneUrl)(`/v1/evm/collectibles/${address}`, queryParams);
32
- const response = await fetch(url);
33
- if (!response.ok) {
34
- throw new Error(`Failed to fetch collectibles: ${response.statusText}`);
35
- }
36
- const data = await response.json();
37
- return data;
38
- }
39
- /**
40
- * Transforms Simdune collectibles response to SimpleHash NFT format
41
- * for compatibility with existing AccountAssets component
42
- */
43
- function transformToSimpleHashFormat(data) {
44
- const nfts = data.entries.map(entry => ({
45
- nft_id: `${entry.chain}.${entry.contract_address}.${entry.token_id}`,
46
- chain: entry.chain,
47
- contract_address: entry.contract_address,
48
- token_id: entry.token_id,
49
- name: entry.name || "",
50
- description: entry.description || "",
51
- previews: {
52
- image_small_url: entry.image_url || "",
53
- image_medium_url: entry.image_url || "",
54
- image_large_url: entry.image_url || "",
55
- image_opengraph_url: entry.image_url || "",
56
- blurhash: "",
57
- predominant_color: "",
58
- },
59
- image_url: entry.image_url || "",
60
- image_properties: {
61
- width: 0,
62
- height: 0,
63
- size: 0,
64
- mime_type: "",
65
- exif_orientation: null,
66
- },
67
- video_url: null,
68
- video_properties: null,
69
- audio_url: null,
70
- audio_properties: null,
71
- model_url: null,
72
- model_properties: null,
73
- other_url: null,
74
- other_properties: null,
75
- background_color: null,
76
- external_url: null,
77
- created_date: "",
78
- status: "minted",
79
- token_count: 1,
80
- owner_count: 1,
81
- owners: [
82
- {
83
- owner_address: data.address,
84
- quantity: safeParseBalance(entry.balance),
85
- quantity_string: entry.balance || "1",
86
- first_acquired_date: entry.last_acquired || "",
87
- last_acquired_date: entry.last_acquired || "",
88
- },
89
- ],
90
- contract: {
91
- type: entry.token_standard,
92
- name: entry.name || "",
93
- symbol: entry.symbol || null,
94
- deployed_by: "",
95
- deployed_via_contract: "",
96
- owned_by: "",
97
- has_multiple_collections: false,
98
- },
99
- collection: {
100
- collection_id: entry.contract_address,
101
- name: entry.symbol || "Unknown Collection",
102
- description: null,
103
- image_url: entry.image_url || "",
104
- image_properties: {
105
- width: 0,
106
- height: 0,
107
- mime_type: "",
108
- },
109
- banner_image_url: null,
110
- category: null,
111
- is_nsfw: null,
112
- external_url: null,
113
- twitter_username: null,
114
- discord_url: null,
115
- instagram_username: null,
116
- medium_username: null,
117
- telegram_url: null,
118
- marketplace_pages: [],
119
- metaplex_mint: null,
120
- metaplex_candy_machine: null,
121
- metaplex_first_verified_creator: null,
122
- floor_prices: [],
123
- top_bids: [],
124
- distinct_owner_count: 0,
125
- distinct_nft_count: 0,
126
- total_quantity: 0,
127
- chains: [entry.chain],
128
- top_contracts: [entry.contract_address],
129
- collection_royalties: [],
130
- },
131
- last_sale: entry.last_sale_price
132
- ? {
133
- price: entry.last_sale_price,
134
- }
135
- : null,
136
- primary_sale: null,
137
- first_created: {
138
- minted_to: data.address,
139
- quantity: 1,
140
- quantity_string: "1",
141
- timestamp: "",
142
- block_number: 0,
143
- transaction: "",
144
- transaction_initiator: "",
145
- },
146
- rarity: {
147
- rank: null,
148
- score: null,
149
- unique_attributes: null,
150
- },
151
- royalty: [],
152
- extra_metadata: {
153
- attributes: (entry.metadata?.attributes || []).map(attr => ({
154
- trait_type: attr.trait_type,
155
- value: attr.value,
156
- display_type: attr.display_type ?? null,
157
- })),
158
- image_original_url: entry.image_url || "",
159
- animation_original_url: null,
160
- metadata_original_url: entry.metadata?.uri || "",
161
- },
162
- }));
163
- return {
164
- next_cursor: data.next_offset || null,
165
- next: null,
166
- previous: null,
167
- nfts,
168
- };
169
- }
170
- /**
171
- * Hook to fetch NFT collectibles from Simdune API.
172
- * Returns data in SimpleHash format for compatibility with AccountAssets component.
173
- * @param address - Wallet address to fetch collectibles for
174
- * @param chainIdsParam - Optional array of chain IDs to filter by
175
- * @param options - Optional parameters (limit, filterSpam)
176
- */
177
- function useSimCollectibles(address, chainIdsParam, options) {
178
- return (0, react_query_1.useQuery)({
179
- queryKey: ["simCollectibles", address, chainIdsParam, options],
180
- queryFn: async () => {
181
- if (!address)
182
- throw new Error("Address is required");
183
- const data = await fetchSimCollectibles(address, chainIdsParam, options);
184
- return transformToSimpleHashFormat(data);
185
- },
186
- enabled: Boolean(address),
187
- staleTime: 30 * 1000,
188
- gcTime: 5 * 60 * 1000,
189
- });
190
- }
@@ -1,7 +0,0 @@
1
- export declare const SIMDUNE_API_HOST = "https://simdune-api.sean-430.workers.dev";
2
- /**
3
- * Builds a Simdune API URL with the proxy wrapper and optional dev mode key.
4
- * @param endpoint - The Simdune API endpoint (e.g., "/v1/evm/balances/0x...")
5
- * @param queryParams - Optional URLSearchParams to append
6
- */
7
- export declare function buildSimduneUrl(endpoint: string, queryParams?: URLSearchParams): string;
@@ -1,21 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SIMDUNE_API_HOST = void 0;
4
- exports.buildSimduneUrl = buildSimduneUrl;
5
- exports.SIMDUNE_API_HOST = "https://simdune-api.sean-430.workers.dev";
6
- /**
7
- * Builds a Simdune API URL with the proxy wrapper and optional dev mode key.
8
- * @param endpoint - The Simdune API endpoint (e.g., "/v1/evm/balances/0x...")
9
- * @param queryParams - Optional URLSearchParams to append
10
- */
11
- function buildSimduneUrl(endpoint, queryParams) {
12
- const baseUrl = `${exports.SIMDUNE_API_HOST}/?url=https://api.sim.dune.com${endpoint}`;
13
- let url = baseUrl;
14
- if (queryParams && queryParams.toString()) {
15
- url += `?${queryParams.toString()}`;
16
- }
17
- if (process.env.NEXT_PUBLIC_DEVMODE_SHARED_SECRET) {
18
- url += `${queryParams?.toString() ? "&" : "?"}localkey=${process.env.NEXT_PUBLIC_DEVMODE_SHARED_SECRET}`;
19
- }
20
- return url;
21
- }