boing-sdk 0.3.0

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 (186) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +191 -0
  3. package/dist/accessList.d.ts +22 -0
  4. package/dist/accessList.d.ts.map +1 -0
  5. package/dist/accessList.js +45 -0
  6. package/dist/bincode.d.ts +92 -0
  7. package/dist/bincode.d.ts.map +1 -0
  8. package/dist/bincode.js +154 -0
  9. package/dist/callAbi.d.ts +119 -0
  10. package/dist/callAbi.d.ts.map +1 -0
  11. package/dist/callAbi.js +156 -0
  12. package/dist/calldata.d.ts +35 -0
  13. package/dist/calldata.d.ts.map +1 -0
  14. package/dist/calldata.js +93 -0
  15. package/dist/canonicalDeployArtifacts.d.ts +154 -0
  16. package/dist/canonicalDeployArtifacts.d.ts.map +1 -0
  17. package/dist/canonicalDeployArtifacts.js +271 -0
  18. package/dist/canonicalTestnet.d.ts +15 -0
  19. package/dist/canonicalTestnet.d.ts.map +1 -0
  20. package/dist/canonicalTestnet.js +15 -0
  21. package/dist/canonicalTestnetDex.d.ts +17 -0
  22. package/dist/canonicalTestnetDex.d.ts.map +1 -0
  23. package/dist/canonicalTestnetDex.js +17 -0
  24. package/dist/chainIds.d.ts +18 -0
  25. package/dist/chainIds.d.ts.map +1 -0
  26. package/dist/chainIds.js +56 -0
  27. package/dist/client.d.ts +223 -0
  28. package/dist/client.d.ts.map +1 -0
  29. package/dist/client.js +659 -0
  30. package/dist/connectionMonitor.d.ts +47 -0
  31. package/dist/connectionMonitor.d.ts.map +1 -0
  32. package/dist/connectionMonitor.js +93 -0
  33. package/dist/create2.d.ts +94 -0
  34. package/dist/create2.d.ts.map +1 -0
  35. package/dist/create2.js +225 -0
  36. package/dist/dappDeploy.d.ts +100 -0
  37. package/dist/dappDeploy.d.ts.map +1 -0
  38. package/dist/dappDeploy.js +140 -0
  39. package/dist/dappUiHelpers.d.ts +28 -0
  40. package/dist/dappUiHelpers.d.ts.map +1 -0
  41. package/dist/dappUiHelpers.js +69 -0
  42. package/dist/defaultReferenceFungibleSecuredRuntimeBytecodeHex.d.ts +6 -0
  43. package/dist/defaultReferenceFungibleSecuredRuntimeBytecodeHex.d.ts.map +1 -0
  44. package/dist/defaultReferenceFungibleSecuredRuntimeBytecodeHex.js +5 -0
  45. package/dist/defaultReferenceFungibleSecuredTemplateBytecodeHex.d.ts +6 -0
  46. package/dist/defaultReferenceFungibleSecuredTemplateBytecodeHex.d.ts.map +1 -0
  47. package/dist/defaultReferenceFungibleSecuredTemplateBytecodeHex.js +5 -0
  48. package/dist/defaultReferenceFungibleTemplateBytecodeHex.d.ts +6 -0
  49. package/dist/defaultReferenceFungibleTemplateBytecodeHex.d.ts.map +1 -0
  50. package/dist/defaultReferenceFungibleTemplateBytecodeHex.js +5 -0
  51. package/dist/defaultReferenceNftCollectionTemplateBytecodeHex.d.ts +7 -0
  52. package/dist/defaultReferenceNftCollectionTemplateBytecodeHex.d.ts.map +1 -0
  53. package/dist/defaultReferenceNftCollectionTemplateBytecodeHex.js +6 -0
  54. package/dist/dexIntegration.d.ts +61 -0
  55. package/dist/dexIntegration.d.ts.map +1 -0
  56. package/dist/dexIntegration.js +193 -0
  57. package/dist/erc721Logs.d.ts +21 -0
  58. package/dist/erc721Logs.d.ts.map +1 -0
  59. package/dist/erc721Logs.js +69 -0
  60. package/dist/errors.d.ts +60 -0
  61. package/dist/errors.d.ts.map +1 -0
  62. package/dist/errors.js +153 -0
  63. package/dist/hex.d.ts +27 -0
  64. package/dist/hex.d.ts.map +1 -0
  65. package/dist/hex.js +82 -0
  66. package/dist/index.d.ts +83 -0
  67. package/dist/index.d.ts.map +1 -0
  68. package/dist/index.js +78 -0
  69. package/dist/indexerBatch.d.ts +111 -0
  70. package/dist/indexerBatch.d.ts.map +1 -0
  71. package/dist/indexerBatch.js +253 -0
  72. package/dist/indexerGaps.d.ts +50 -0
  73. package/dist/indexerGaps.d.ts.map +1 -0
  74. package/dist/indexerGaps.js +117 -0
  75. package/dist/indexerSync.d.ts +61 -0
  76. package/dist/indexerSync.d.ts.map +1 -0
  77. package/dist/indexerSync.js +100 -0
  78. package/dist/nativeAmm.d.ts +64 -0
  79. package/dist/nativeAmm.d.ts.map +1 -0
  80. package/dist/nativeAmm.js +174 -0
  81. package/dist/nativeAmmLogs.d.ts +48 -0
  82. package/dist/nativeAmmLogs.d.ts.map +1 -0
  83. package/dist/nativeAmmLogs.js +114 -0
  84. package/dist/nativeAmmLpVault.d.ts +94 -0
  85. package/dist/nativeAmmLpVault.d.ts.map +1 -0
  86. package/dist/nativeAmmLpVault.js +205 -0
  87. package/dist/nativeAmmPool.d.ts +124 -0
  88. package/dist/nativeAmmPool.d.ts.map +1 -0
  89. package/dist/nativeAmmPool.js +245 -0
  90. package/dist/nativeContractSubmit.d.ts +26 -0
  91. package/dist/nativeContractSubmit.d.ts.map +1 -0
  92. package/dist/nativeContractSubmit.js +23 -0
  93. package/dist/nativeDexDirectory.d.ts +83 -0
  94. package/dist/nativeDexDirectory.d.ts.map +1 -0
  95. package/dist/nativeDexDirectory.js +147 -0
  96. package/dist/nativeDexDirectoryApi.d.ts +121 -0
  97. package/dist/nativeDexDirectoryApi.d.ts.map +1 -0
  98. package/dist/nativeDexDirectoryApi.js +408 -0
  99. package/dist/nativeDexFactory.d.ts +25 -0
  100. package/dist/nativeDexFactory.d.ts.map +1 -0
  101. package/dist/nativeDexFactory.js +72 -0
  102. package/dist/nativeDexFactoryLogs.d.ts +19 -0
  103. package/dist/nativeDexFactoryLogs.d.ts.map +1 -0
  104. package/dist/nativeDexFactoryLogs.js +61 -0
  105. package/dist/nativeDexFactoryPool.d.ts +61 -0
  106. package/dist/nativeDexFactoryPool.d.ts.map +1 -0
  107. package/dist/nativeDexFactoryPool.js +120 -0
  108. package/dist/nativeDexIndexerStats.d.ts +96 -0
  109. package/dist/nativeDexIndexerStats.d.ts.map +1 -0
  110. package/dist/nativeDexIndexerStats.js +448 -0
  111. package/dist/nativeDexLedgerRouter.d.ts +67 -0
  112. package/dist/nativeDexLedgerRouter.d.ts.map +1 -0
  113. package/dist/nativeDexLedgerRouter.js +108 -0
  114. package/dist/nativeDexLpPositions.d.ts +39 -0
  115. package/dist/nativeDexLpPositions.d.ts.map +1 -0
  116. package/dist/nativeDexLpPositions.js +69 -0
  117. package/dist/nativeDexNftIndexer.d.ts +26 -0
  118. package/dist/nativeDexNftIndexer.d.ts.map +1 -0
  119. package/dist/nativeDexNftIndexer.js +50 -0
  120. package/dist/nativeDexPoolHistory.d.ts +40 -0
  121. package/dist/nativeDexPoolHistory.d.ts.map +1 -0
  122. package/dist/nativeDexPoolHistory.js +110 -0
  123. package/dist/nativeDexReceiptArchive.d.ts +25 -0
  124. package/dist/nativeDexReceiptArchive.d.ts.map +1 -0
  125. package/dist/nativeDexReceiptArchive.js +47 -0
  126. package/dist/nativeDexRouting.d.ts +160 -0
  127. package/dist/nativeDexRouting.d.ts.map +1 -0
  128. package/dist/nativeDexRouting.js +345 -0
  129. package/dist/nativeDexSeamless.d.ts +86 -0
  130. package/dist/nativeDexSeamless.d.ts.map +1 -0
  131. package/dist/nativeDexSeamless.js +131 -0
  132. package/dist/nativeDexSwap2Router.d.ts +45 -0
  133. package/dist/nativeDexSwap2Router.d.ts.map +1 -0
  134. package/dist/nativeDexSwap2Router.js +276 -0
  135. package/dist/nativeLpShareToken.d.ts +54 -0
  136. package/dist/nativeLpShareToken.d.ts.map +1 -0
  137. package/dist/nativeLpShareToken.js +135 -0
  138. package/dist/nativeTokenSecurity.d.ts +59 -0
  139. package/dist/nativeTokenSecurity.d.ts.map +1 -0
  140. package/dist/nativeTokenSecurity.js +59 -0
  141. package/dist/networkProfile.d.ts +8 -0
  142. package/dist/networkProfile.d.ts.map +1 -0
  143. package/dist/networkProfile.js +29 -0
  144. package/dist/newHeadsWs.d.ts +43 -0
  145. package/dist/newHeadsWs.d.ts.map +1 -0
  146. package/dist/newHeadsWs.js +139 -0
  147. package/dist/preflightGate.d.ts +16 -0
  148. package/dist/preflightGate.d.ts.map +1 -0
  149. package/dist/preflightGate.js +29 -0
  150. package/dist/receiptLogs.d.ts +29 -0
  151. package/dist/receiptLogs.d.ts.map +1 -0
  152. package/dist/receiptLogs.js +66 -0
  153. package/dist/referenceFungibleSecuredDeployBytecode.d.ts +54 -0
  154. package/dist/referenceFungibleSecuredDeployBytecode.d.ts.map +1 -0
  155. package/dist/referenceFungibleSecuredDeployBytecode.js +274 -0
  156. package/dist/referenceNft.d.ts +14 -0
  157. package/dist/referenceNft.d.ts.map +1 -0
  158. package/dist/referenceNft.js +34 -0
  159. package/dist/referenceToken.d.ts +14 -0
  160. package/dist/referenceToken.d.ts.map +1 -0
  161. package/dist/referenceToken.js +29 -0
  162. package/dist/retryAfter.d.ts +6 -0
  163. package/dist/retryAfter.d.ts.map +1 -0
  164. package/dist/retryAfter.js +24 -0
  165. package/dist/rpcCapabilities.d.ts +43 -0
  166. package/dist/rpcCapabilities.d.ts.map +1 -0
  167. package/dist/rpcCapabilities.js +159 -0
  168. package/dist/rpcDoctor.d.ts +27 -0
  169. package/dist/rpcDoctor.d.ts.map +1 -0
  170. package/dist/rpcDoctor.js +66 -0
  171. package/dist/rpcSurfaceUi.d.ts +32 -0
  172. package/dist/rpcSurfaceUi.d.ts.map +1 -0
  173. package/dist/rpcSurfaceUi.js +49 -0
  174. package/dist/submitFlow.d.ts +70 -0
  175. package/dist/submitFlow.d.ts.map +1 -0
  176. package/dist/submitFlow.js +121 -0
  177. package/dist/transactionBuilder.d.ts +55 -0
  178. package/dist/transactionBuilder.d.ts.map +1 -0
  179. package/dist/transactionBuilder.js +100 -0
  180. package/dist/types.d.ts +436 -0
  181. package/dist/types.d.ts.map +1 -0
  182. package/dist/types.js +4 -0
  183. package/dist/walletProvider.d.ts +46 -0
  184. package/dist/walletProvider.d.ts.map +1 -0
  185. package/dist/walletProvider.js +126 -0
  186. package/package.json +44 -0
@@ -0,0 +1,193 @@
1
+ /**
2
+ * One-call defaults for native Boing DEX wiring: merge **`boing_getNetworkInfo.end_user`**
3
+ * hints with embedded testnet fallbacks and app overrides.
4
+ *
5
+ * See [BOING-DAPP-INTEGRATION.md](../../docs/BOING-DAPP-INTEGRATION.md) § **Seamless native DEX defaults**.
6
+ */
7
+ import { CANONICAL_BOING_TESTNET_NATIVE_CP_POOL_HEX } from './canonicalTestnet.js';
8
+ import { CANONICAL_BOING_TESTNET_NATIVE_AMM_LP_VAULT_HEX, CANONICAL_BOING_TESTNET_NATIVE_DEX_FACTORY_HEX, CANONICAL_BOING_TESTNET_NATIVE_DEX_LEDGER_ROUTER_V2_HEX, CANONICAL_BOING_TESTNET_NATIVE_DEX_LEDGER_ROUTER_V3_HEX, CANONICAL_BOING_TESTNET_NATIVE_DEX_MULTIHOP_SWAP_ROUTER_HEX, CANONICAL_BOING_TESTNET_NATIVE_LP_SHARE_TOKEN_HEX, } from './canonicalTestnetDex.js';
9
+ import { isBoingTestnetChainId } from './chainIds.js';
10
+ import { validateHex32 } from './hex.js';
11
+ import { getLogsChunked } from './indexerBatch.js';
12
+ import { NATIVE_DEX_FACTORY_TOPIC_REGISTER_HEX } from './nativeDexFactory.js';
13
+ import { tryParseNativeDexFactoryRegisterRpcLogEntry, } from './nativeDexFactoryLogs.js';
14
+ function parseOptionalHex32(v) {
15
+ if (v == null || typeof v !== 'string')
16
+ return null;
17
+ const t = v.trim();
18
+ if (!t)
19
+ return null;
20
+ try {
21
+ return validateHex32(t);
22
+ }
23
+ catch {
24
+ return null;
25
+ }
26
+ }
27
+ function mergeOptionalAccountHex(chainId, override, rpcField, embeddedWhenTestnet) {
28
+ const o = override;
29
+ if (o?.trim()) {
30
+ try {
31
+ return { hex: validateHex32(o), source: 'override' };
32
+ }
33
+ catch {
34
+ return { hex: null, source: 'none' };
35
+ }
36
+ }
37
+ const rpc = parseOptionalHex32(rpcField ?? null);
38
+ if (rpc)
39
+ return { hex: rpc, source: 'rpc_end_user' };
40
+ if (chainId != null && isBoingTestnetChainId(chainId) && embeddedWhenTestnet != null) {
41
+ return { hex: embeddedWhenTestnet, source: 'sdk_testnet_embedded' };
42
+ }
43
+ return { hex: null, source: 'none' };
44
+ }
45
+ function getProcessEnvRecord() {
46
+ if (typeof globalThis === 'undefined')
47
+ return undefined;
48
+ const proc = globalThis.process;
49
+ return proc?.env;
50
+ }
51
+ function readFirstProcessEnv(keys) {
52
+ const env = getProcessEnvRecord();
53
+ if (env == null)
54
+ return undefined;
55
+ for (const k of keys) {
56
+ const v = env[k];
57
+ if (v != null && String(v).trim())
58
+ return String(v).trim();
59
+ }
60
+ return undefined;
61
+ }
62
+ /**
63
+ * Build {@link NativeDexIntegrationOverrides} from **`process.env`** (Node / Vite / CRA).
64
+ * First non-empty value wins per key group. Safe to call from browser bundles if env is injected at build time.
65
+ */
66
+ export function buildNativeDexIntegrationOverridesFromProcessEnv() {
67
+ const o = {};
68
+ const pool = readFirstProcessEnv([
69
+ 'REACT_APP_BOING_NATIVE_AMM_POOL',
70
+ 'VITE_BOING_NATIVE_AMM_POOL',
71
+ 'BOING_NATIVE_AMM_POOL',
72
+ ]);
73
+ const fac = readFirstProcessEnv([
74
+ 'REACT_APP_BOING_NATIVE_VM_DEX_FACTORY',
75
+ 'VITE_BOING_NATIVE_VM_DEX_FACTORY',
76
+ 'BOING_NATIVE_VM_DEX_FACTORY',
77
+ 'BOING_DEX_FACTORY_HEX',
78
+ ]);
79
+ const hop = readFirstProcessEnv([
80
+ 'REACT_APP_BOING_NATIVE_VM_SWAP_ROUTER',
81
+ 'VITE_BOING_NATIVE_VM_SWAP_ROUTER',
82
+ 'BOING_NATIVE_VM_SWAP_ROUTER',
83
+ 'BOING_NATIVE_DEX_MULTIHOP_SWAP_ROUTER',
84
+ ]);
85
+ const l2 = readFirstProcessEnv([
86
+ 'REACT_APP_BOING_NATIVE_DEX_LEDGER_ROUTER_V2',
87
+ 'VITE_BOING_NATIVE_DEX_LEDGER_ROUTER_V2',
88
+ 'BOING_NATIVE_DEX_LEDGER_ROUTER_V2',
89
+ ]);
90
+ const l3 = readFirstProcessEnv([
91
+ 'REACT_APP_BOING_NATIVE_DEX_LEDGER_ROUTER_V3',
92
+ 'VITE_BOING_NATIVE_DEX_LEDGER_ROUTER_V3',
93
+ 'BOING_NATIVE_DEX_LEDGER_ROUTER_V3',
94
+ ]);
95
+ const vault = readFirstProcessEnv([
96
+ 'REACT_APP_BOING_NATIVE_AMM_LP_VAULT',
97
+ 'VITE_BOING_NATIVE_AMM_LP_VAULT',
98
+ 'BOING_NATIVE_AMM_LP_VAULT',
99
+ ]);
100
+ const share = readFirstProcessEnv([
101
+ 'REACT_APP_BOING_NATIVE_AMM_LP_SHARE_TOKEN',
102
+ 'VITE_BOING_NATIVE_AMM_LP_SHARE_TOKEN',
103
+ 'BOING_NATIVE_AMM_LP_SHARE_TOKEN',
104
+ ]);
105
+ if (pool)
106
+ o.nativeCpPoolAccountHex = pool;
107
+ if (fac)
108
+ o.nativeDexFactoryAccountHex = fac;
109
+ if (hop)
110
+ o.nativeDexMultihopSwapRouterAccountHex = hop;
111
+ if (l2)
112
+ o.nativeDexLedgerRouterV2AccountHex = l2;
113
+ if (l3)
114
+ o.nativeDexLedgerRouterV3AccountHex = l3;
115
+ if (vault)
116
+ o.nativeAmmLpVaultAccountHex = vault;
117
+ if (share)
118
+ o.nativeLpShareTokenAccountHex = share;
119
+ return o;
120
+ }
121
+ /**
122
+ * Merge RPC **`end_user`** canonical addresses, optional app overrides, and embedded **6913** fallbacks
123
+ * (see [`canonicalTestnetDex.ts`](./canonicalTestnetDex.ts)).
124
+ * Order per field: overrides → node hints → testnet embedded constants.
125
+ */
126
+ export function mergeNativeDexIntegrationDefaults(info, overrides) {
127
+ const chainId = info?.chain_id ?? null;
128
+ const eu = info?.end_user;
129
+ const poolEmb = CANONICAL_BOING_TESTNET_NATIVE_CP_POOL_HEX;
130
+ const facEmb = CANONICAL_BOING_TESTNET_NATIVE_DEX_FACTORY_HEX;
131
+ const hopEmb = CANONICAL_BOING_TESTNET_NATIVE_DEX_MULTIHOP_SWAP_ROUTER_HEX;
132
+ const l2Emb = CANONICAL_BOING_TESTNET_NATIVE_DEX_LEDGER_ROUTER_V2_HEX;
133
+ const l3Emb = CANONICAL_BOING_TESTNET_NATIVE_DEX_LEDGER_ROUTER_V3_HEX;
134
+ const vaultEmb = CANONICAL_BOING_TESTNET_NATIVE_AMM_LP_VAULT_HEX;
135
+ const shareEmb = CANONICAL_BOING_TESTNET_NATIVE_LP_SHARE_TOKEN_HEX;
136
+ const pool = mergeOptionalAccountHex(chainId, overrides?.nativeCpPoolAccountHex, eu?.canonical_native_cp_pool ?? null, poolEmb);
137
+ const factory = mergeOptionalAccountHex(chainId, overrides?.nativeDexFactoryAccountHex, eu?.canonical_native_dex_factory ?? null, facEmb);
138
+ const multihop = mergeOptionalAccountHex(chainId, overrides?.nativeDexMultihopSwapRouterAccountHex, eu?.canonical_native_dex_multihop_swap_router ?? null, hopEmb);
139
+ const ledgerV2 = mergeOptionalAccountHex(chainId, overrides?.nativeDexLedgerRouterV2AccountHex, eu?.canonical_native_dex_ledger_router_v2 ?? null, l2Emb);
140
+ const ledgerV3 = mergeOptionalAccountHex(chainId, overrides?.nativeDexLedgerRouterV3AccountHex, eu?.canonical_native_dex_ledger_router_v3 ?? null, l3Emb);
141
+ const vault = mergeOptionalAccountHex(chainId, overrides?.nativeAmmLpVaultAccountHex, eu?.canonical_native_amm_lp_vault ?? null, vaultEmb);
142
+ const share = mergeOptionalAccountHex(chainId, overrides?.nativeLpShareTokenAccountHex, eu?.canonical_native_lp_share_token ?? null, shareEmb);
143
+ let endUserExplorerUrl = null;
144
+ const ex = eu?.explorer_url;
145
+ if (typeof ex === 'string') {
146
+ const t = ex.trim();
147
+ if (t && /^https?:\/\//i.test(t)) {
148
+ endUserExplorerUrl = t.replace(/\/+$/, '');
149
+ }
150
+ }
151
+ return {
152
+ nativeCpPoolAccountHex: pool.hex,
153
+ nativeDexFactoryAccountHex: factory.hex,
154
+ poolSource: pool.source,
155
+ factorySource: factory.source,
156
+ nativeDexMultihopSwapRouterAccountHex: multihop.hex,
157
+ nativeDexMultihopSwapRouterSource: multihop.source,
158
+ nativeDexLedgerRouterV2AccountHex: ledgerV2.hex,
159
+ nativeDexLedgerRouterV2Source: ledgerV2.source,
160
+ nativeDexLedgerRouterV3AccountHex: ledgerV3.hex,
161
+ nativeDexLedgerRouterV3Source: ledgerV3.source,
162
+ nativeAmmLpVaultAccountHex: vault.hex,
163
+ nativeAmmLpVaultSource: vault.source,
164
+ nativeLpShareTokenAccountHex: share.hex,
165
+ nativeLpShareTokenSource: share.source,
166
+ endUserExplorerUrl,
167
+ };
168
+ }
169
+ /** Fetch **`boing_getNetworkInfo`** and {@link mergeNativeDexIntegrationDefaults}. */
170
+ export async function fetchNativeDexIntegrationDefaults(client, overrides) {
171
+ const info = await client.getNetworkInfo();
172
+ return mergeNativeDexIntegrationDefaults(info, overrides);
173
+ }
174
+ /**
175
+ * Stream **`register_pair`** **`Log3`** rows for a factory (chunked **`boing_getLogs`**).
176
+ * Requires a known factory **`AccountId`** (from {@link NativeDexIntegrationDefaults} or CREATE2 prediction).
177
+ */
178
+ export async function fetchNativeDexFactoryRegisterLogs(client, opts) {
179
+ const factoryAccountHex = validateHex32(opts.factoryAccountHex);
180
+ const raw = await getLogsChunked(client, {
181
+ fromBlock: opts.fromBlock,
182
+ toBlock: opts.toBlock,
183
+ address: factoryAccountHex,
184
+ topics: [NATIVE_DEX_FACTORY_TOPIC_REGISTER_HEX, null, null],
185
+ }, {});
186
+ const out = [];
187
+ for (const row of raw) {
188
+ const p = tryParseNativeDexFactoryRegisterRpcLogEntry(row);
189
+ if (p)
190
+ out.push(p);
191
+ }
192
+ return out;
193
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * ERC-721 **`Transfer(address,address,uint256)`** log parsing for indexer-style **`boing_getLogs`** rows.
3
+ * Topic0 matches Ethereum’s canonical event signature (same as widely used EVM tooling).
4
+ */
5
+ import type { RpcLogEntry } from './types.js';
6
+ /** `keccak256("Transfer(address,address,uint256)")` topic0 (lowercase `0x` + 64 hex). */
7
+ export declare const ERC721_TRANSFER_TOPIC0_HEX: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
8
+ export type Erc721TransferParsed = {
9
+ fromHex: `0x${string}`;
10
+ toHex: `0x${string}`;
11
+ tokenId: bigint;
12
+ blockHeight: number;
13
+ txId: string;
14
+ logIndex: number;
15
+ };
16
+ /**
17
+ * Parse one **`Transfer`** log (`4` topics: signature + indexed from + to + tokenId).
18
+ */
19
+ export declare function tryParseErc721TransferRpcLog(entry: RpcLogEntry): Erc721TransferParsed | null;
20
+ export declare function filterMapErc721TransferRpcLogs(entries: readonly RpcLogEntry[]): Erc721TransferParsed[];
21
+ //# sourceMappingURL=erc721Logs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"erc721Logs.d.ts","sourceRoot":"","sources":["../src/erc721Logs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,yFAAyF;AACzF,eAAO,MAAM,0BAA0B,EACrC,oEAA6E,CAAC;AAwBhF,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,KAAK,MAAM,EAAE,CAAC;IACvB,KAAK,EAAE,KAAK,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,WAAW,GAAG,oBAAoB,GAAG,IAAI,CAoB5F;AAED,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG,oBAAoB,EAAE,CAOtG"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * ERC-721 **`Transfer(address,address,uint256)`** log parsing for indexer-style **`boing_getLogs`** rows.
3
+ * Topic0 matches Ethereum’s canonical event signature (same as widely used EVM tooling).
4
+ */
5
+ import { normalizeTopicWord } from './receiptLogs.js';
6
+ /** `keccak256("Transfer(address,address,uint256)")` topic0 (lowercase `0x` + 64 hex). */
7
+ export const ERC721_TRANSFER_TOPIC0_HEX = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
8
+ function topicAddressToAccountHex32(topic) {
9
+ try {
10
+ const t = normalizeTopicWord(topic);
11
+ if (t.length !== 66)
12
+ return null;
13
+ const addr20 = t.slice(-40).toLowerCase();
14
+ if (!/^[0-9a-f]{40}$/.test(addr20))
15
+ return null;
16
+ return (`0x${'00'.repeat(12)}${addr20}`);
17
+ }
18
+ catch {
19
+ return null;
20
+ }
21
+ }
22
+ function topicUint256ToBigInt(topic) {
23
+ try {
24
+ const t = normalizeTopicWord(topic);
25
+ if (t.length !== 66)
26
+ return null;
27
+ return BigInt(t);
28
+ }
29
+ catch {
30
+ return null;
31
+ }
32
+ }
33
+ /**
34
+ * Parse one **`Transfer`** log (`4` topics: signature + indexed from + to + tokenId).
35
+ */
36
+ export function tryParseErc721TransferRpcLog(entry) {
37
+ try {
38
+ const t0 = normalizeTopicWord(entry.topics[0] ?? '');
39
+ if (t0 !== ERC721_TRANSFER_TOPIC0_HEX)
40
+ return null;
41
+ if (entry.topics.length !== 4)
42
+ return null;
43
+ const from32 = topicAddressToAccountHex32(entry.topics[1]);
44
+ const to32 = topicAddressToAccountHex32(entry.topics[2]);
45
+ const tid = topicUint256ToBigInt(entry.topics[3]);
46
+ if (from32 == null || to32 == null || tid == null)
47
+ return null;
48
+ return {
49
+ fromHex: from32.toLowerCase(),
50
+ toHex: to32.toLowerCase(),
51
+ tokenId: tid,
52
+ blockHeight: entry.block_height,
53
+ txId: entry.tx_id,
54
+ logIndex: entry.log_index,
55
+ };
56
+ }
57
+ catch {
58
+ return null;
59
+ }
60
+ }
61
+ export function filterMapErc721TransferRpcLogs(entries) {
62
+ const out = [];
63
+ for (const e of entries) {
64
+ const p = tryParseErc721TransferRpcLog(e);
65
+ if (p)
66
+ out.push(p);
67
+ }
68
+ return out;
69
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * RPC error with optional structured data (e.g. QA rejection rule_id and message).
3
+ * When thrown from BoingClient, `method` is set to the RPC method that failed.
4
+ */
5
+ export declare class BoingRpcError extends Error {
6
+ readonly code: number;
7
+ readonly data?: unknown | undefined;
8
+ /** RPC method that failed (e.g. "boing_getBalance"). */
9
+ readonly method?: string | undefined;
10
+ /**
11
+ * From HTTP **`Retry-After`** when the server returned a retriable status (e.g. 429).
12
+ * Used by `BoingClient` to wait at least this long before the next retry.
13
+ */
14
+ readonly retryAfterMs?: number | undefined;
15
+ constructor(code: number, message: string, data?: unknown | undefined,
16
+ /** RPC method that failed (e.g. "boing_getBalance"). */
17
+ method?: string | undefined,
18
+ /**
19
+ * From HTTP **`Retry-After`** when the server returned a retriable status (e.g. 429).
20
+ * Used by `BoingClient` to wait at least this long before the next retry.
21
+ */
22
+ retryAfterMs?: number | undefined);
23
+ /** Short string for logging: "BoingRpcError(code, method): message". */
24
+ toString(): string;
25
+ /** True if this is a QA deployment rejection (-32050). */
26
+ get isQaRejected(): boolean;
27
+ /** True if deployment was referred to governance QA pool (-32051). */
28
+ get isQaPendingPool(): boolean;
29
+ /** True if QA pool is disabled by governance (-32054). */
30
+ get isQaPoolDisabled(): boolean;
31
+ /** True if QA pool hit global max pending (-32055). */
32
+ get isQaPoolFull(): boolean;
33
+ /** True if deployer exceeded per-address pool cap (-32056). */
34
+ get isQaPoolDeployerCap(): boolean;
35
+ /** True if the node rejected the call due to HTTP JSON-RPC rate limiting (-32016). */
36
+ get isRateLimited(): boolean;
37
+ /** For -32051, `data.tx_hash` when present. */
38
+ get pendingPoolTxHash(): string | undefined;
39
+ /** QA rejection details when code is -32050. */
40
+ get qaData(): {
41
+ rule_id: string;
42
+ message: string;
43
+ } | undefined;
44
+ }
45
+ /**
46
+ * JSON-RPC 2.0 **method not found** (-32601). Common when the endpoint is an older Boing node or a
47
+ * proxy that does not implement a newer `boing_*` method (e.g. `boing_getSyncState`, `boing_getLogs`).
48
+ */
49
+ export declare function isBoingRpcMethodNotFound(e: unknown): boolean;
50
+ /**
51
+ * Whether a failed call is worth retrying (transient HTTP, rate limits, network).
52
+ * Application errors (e.g. invalid nonce, QA rejection) return false.
53
+ */
54
+ export declare function isRetriableBoingRpcError(e: unknown): boolean;
55
+ /**
56
+ * User-facing explanation for logging and UI (maps Boing JSON-RPC codes to short text).
57
+ * See `docs/BOING-RPC-ERROR-CODES-FOR-DAPPS.md` in the boing-network repo.
58
+ */
59
+ export declare function explainBoingRpcError(e: unknown): string;
60
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,aAAc,SAAQ,KAAK;aAEpB,IAAI,EAAE,MAAM;aAEZ,IAAI,CAAC,EAAE,OAAO;IAC9B,wDAAwD;aACxC,MAAM,CAAC,EAAE,MAAM;IAC/B;;;OAGG;aACa,YAAY,CAAC,EAAE,MAAM;gBATrB,IAAI,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM,EACC,IAAI,CAAC,EAAE,OAAO,YAAA;IAC9B,wDAAwD;IACxC,MAAM,CAAC,EAAE,MAAM,YAAA;IAC/B;;;OAGG;IACa,YAAY,CAAC,EAAE,MAAM,YAAA;IAOvC,wEAAwE;IAC/D,QAAQ,IAAI,MAAM;IAK3B,0DAA0D;IAC1D,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED,sEAAsE;IACtE,IAAI,eAAe,IAAI,OAAO,CAE7B;IAED,0DAA0D;IAC1D,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED,uDAAuD;IACvD,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED,+DAA+D;IAC/D,IAAI,mBAAmB,IAAI,OAAO,CAEjC;IAED,sFAAsF;IACtF,IAAI,aAAa,IAAI,OAAO,CAE3B;IAED,+CAA+C;IAC/C,IAAI,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAI1C;IAED,gDAAgD;IAChD,IAAI,MAAM,IAAI;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAO7D;CACF;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAE5D;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAc5D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAwCvD"}
package/dist/errors.js ADDED
@@ -0,0 +1,153 @@
1
+ /**
2
+ * RPC error with optional structured data (e.g. QA rejection rule_id and message).
3
+ * When thrown from BoingClient, `method` is set to the RPC method that failed.
4
+ */
5
+ export class BoingRpcError extends Error {
6
+ constructor(code, message, data,
7
+ /** RPC method that failed (e.g. "boing_getBalance"). */
8
+ method,
9
+ /**
10
+ * From HTTP **`Retry-After`** when the server returned a retriable status (e.g. 429).
11
+ * Used by `BoingClient` to wait at least this long before the next retry.
12
+ */
13
+ retryAfterMs) {
14
+ super(message);
15
+ this.code = code;
16
+ this.data = data;
17
+ this.method = method;
18
+ this.retryAfterMs = retryAfterMs;
19
+ this.name = 'BoingRpcError';
20
+ Object.setPrototypeOf(this, BoingRpcError.prototype);
21
+ }
22
+ /** Short string for logging: "BoingRpcError(code, method): message". */
23
+ toString() {
24
+ const method = this.method ? ` ${this.method}` : '';
25
+ return `BoingRpcError(${this.code}${method}): ${this.message}`;
26
+ }
27
+ /** True if this is a QA deployment rejection (-32050). */
28
+ get isQaRejected() {
29
+ return this.code === -32050;
30
+ }
31
+ /** True if deployment was referred to governance QA pool (-32051). */
32
+ get isQaPendingPool() {
33
+ return this.code === -32051;
34
+ }
35
+ /** True if QA pool is disabled by governance (-32054). */
36
+ get isQaPoolDisabled() {
37
+ return this.code === -32054;
38
+ }
39
+ /** True if QA pool hit global max pending (-32055). */
40
+ get isQaPoolFull() {
41
+ return this.code === -32055;
42
+ }
43
+ /** True if deployer exceeded per-address pool cap (-32056). */
44
+ get isQaPoolDeployerCap() {
45
+ return this.code === -32056;
46
+ }
47
+ /** True if the node rejected the call due to HTTP JSON-RPC rate limiting (-32016). */
48
+ get isRateLimited() {
49
+ return this.code === -32016;
50
+ }
51
+ /** For -32051, `data.tx_hash` when present. */
52
+ get pendingPoolTxHash() {
53
+ if (this.code !== -32051 || !this.data || typeof this.data !== 'object')
54
+ return undefined;
55
+ const d = this.data;
56
+ return typeof d.tx_hash === 'string' ? d.tx_hash : undefined;
57
+ }
58
+ /** QA rejection details when code is -32050. */
59
+ get qaData() {
60
+ if (this.code !== -32050 || !this.data || typeof this.data !== 'object')
61
+ return undefined;
62
+ const d = this.data;
63
+ if (typeof d.rule_id === 'string' && typeof d.message === 'string') {
64
+ return { rule_id: d.rule_id, message: d.message };
65
+ }
66
+ return undefined;
67
+ }
68
+ }
69
+ /**
70
+ * JSON-RPC 2.0 **method not found** (-32601). Common when the endpoint is an older Boing node or a
71
+ * proxy that does not implement a newer `boing_*` method (e.g. `boing_getSyncState`, `boing_getLogs`).
72
+ */
73
+ export function isBoingRpcMethodNotFound(e) {
74
+ return e instanceof BoingRpcError && e.code === -32601;
75
+ }
76
+ /**
77
+ * Whether a failed call is worth retrying (transient HTTP, rate limits, network).
78
+ * Application errors (e.g. invalid nonce, QA rejection) return false.
79
+ */
80
+ export function isRetriableBoingRpcError(e) {
81
+ if (!(e instanceof BoingRpcError))
82
+ return true;
83
+ if (e.isRateLimited)
84
+ return true;
85
+ if (e.code === -32000) {
86
+ const m = e.message;
87
+ if (/\bHTTP 429\b/.test(m))
88
+ return true;
89
+ if (/\bHTTP 502\b/.test(m))
90
+ return true;
91
+ if (/\bHTTP 503\b/.test(m))
92
+ return true;
93
+ if (/\bHTTP 504\b/.test(m))
94
+ return true;
95
+ if (/Request timed out after \d+ms/.test(m))
96
+ return true;
97
+ if (/ECONNRESET|ETIMEDOUT|ENOTFOUND|EAI_AGAIN/i.test(m))
98
+ return true;
99
+ if (/fetch failed|Failed to fetch|Load failed|network/i.test(m))
100
+ return true;
101
+ }
102
+ return false;
103
+ }
104
+ /**
105
+ * User-facing explanation for logging and UI (maps Boing JSON-RPC codes to short text).
106
+ * See `docs/BOING-RPC-ERROR-CODES-FOR-DAPPS.md` in the boing-network repo.
107
+ */
108
+ export function explainBoingRpcError(e) {
109
+ if (e instanceof BoingRpcError) {
110
+ if (e.isQaRejected) {
111
+ const q = e.qaData;
112
+ return q ? `QA rejected (${q.rule_id}): ${q.message}` : `QA rejected: ${e.message}`;
113
+ }
114
+ if (e.isQaPendingPool) {
115
+ const h = e.pendingPoolTxHash;
116
+ return h
117
+ ? `Deployment queued for QA pool (tx_hash ${h}). Vote via boing_qaPoolVote.`
118
+ : `Deployment queued for QA pool: ${e.message}`;
119
+ }
120
+ if (e.isQaPoolDisabled)
121
+ return `QA pool is disabled by governance: ${e.message}`;
122
+ if (e.isQaPoolFull)
123
+ return `QA pool is full (global cap): ${e.message}`;
124
+ if (e.isQaPoolDeployerCap)
125
+ return `QA pool deployer cap reached: ${e.message}`;
126
+ if (e.code === -32057)
127
+ return `Operator RPC authentication required: ${e.message}`;
128
+ if (e.isRateLimited) {
129
+ const hint = e.retryAfterMs != null && e.retryAfterMs > 0
130
+ ? ` Wait at least ${Math.ceil(e.retryAfterMs / 1000)}s (Retry-After header).`
131
+ : '';
132
+ return `Rate limited: ${e.message}.${hint}`;
133
+ }
134
+ if (e.code === -32000 && e.message.includes('413')) {
135
+ return `Request body too large for this RPC endpoint: ${e.message}`;
136
+ }
137
+ if (e.code === -32700)
138
+ return `Invalid JSON in RPC body (parse error): ${e.message}`;
139
+ if (e.code === -32600)
140
+ return `Invalid JSON-RPC request (e.g. batch too large or malformed): ${e.message}`;
141
+ if (e.code === -32601)
142
+ return `RPC method not implemented on this endpoint (old node or filtered proxy): ${e.message}`;
143
+ if (e.code === -32602)
144
+ return `Invalid RPC params: ${e.message}`;
145
+ if (e.code === -32000 && e.retryAfterMs != null && e.retryAfterMs > 0) {
146
+ return `Transient RPC error (wait ~${Math.ceil(e.retryAfterMs / 1000)}s per Retry-After): ${e.message}`;
147
+ }
148
+ return e.toString();
149
+ }
150
+ if (e instanceof Error)
151
+ return e.message;
152
+ return String(e);
153
+ }
package/dist/hex.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Hex encoding/decoding for 32-byte IDs, hashes, and RPC params.
3
+ */
4
+ /** Ensure string has 0x prefix. */
5
+ export declare function ensureHex(s: string): string;
6
+ /** Encode bytes to hex with 0x prefix. */
7
+ export declare function bytesToHex(bytes: Uint8Array): string;
8
+ /** Decode hex string to bytes (with or without 0x). */
9
+ export declare function hexToBytes(hex: string): Uint8Array;
10
+ /**
11
+ * Normalize hex and require exactly 32 bytes (64 hex chars). Use for account IDs and hashes.
12
+ * @returns Hex string with 0x prefix
13
+ * @throws if not valid hex or length is not 64
14
+ */
15
+ export declare function validateHex32(hex: string): string;
16
+ /**
17
+ * Decode a **32-byte** `boing_getContractStorage` **value** word as a Boing **`AccountId`**, or **`null`**
18
+ * if the word is all zero. Truncates/pads to 64 hex chars like other storage decoders.
19
+ */
20
+ export declare function decodeBoingStorageWordAccountId(valueHex: string): `0x${string}` | null;
21
+ /** True if **`hex`** is a valid **32-byte** Boing **`AccountId`** (`0x` + 64 hex). Use to branch wizards away from 20-byte EVM addresses. */
22
+ export declare function isBoingNativeAccountIdHex(hex: string): boolean;
23
+ /** Assert 32-byte buffer; return as hex. */
24
+ export declare function accountIdToHex(bytes: Uint8Array): string;
25
+ /** Parse 32-byte AccountId from hex. */
26
+ export declare function hexToAccountId(hex: string): Uint8Array;
27
+ //# sourceMappingURL=hex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hex.d.ts","sourceRoot":"","sources":["../src/hex.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,mCAAmC;AACnC,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAG3C;AAED,0CAA0C;AAC1C,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAIpD;AAID,uDAAuD;AACvD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CASlD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE,GAAG,IAAI,CAWtF;AAED,6IAA6I;AAC7I,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO9D;AAED,4CAA4C;AAC5C,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAGxD;AAED,wCAAwC;AACxC,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAItD"}
package/dist/hex.js ADDED
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Hex encoding/decoding for 32-byte IDs, hashes, and RPC params.
3
+ */
4
+ /** Ensure string has 0x prefix. */
5
+ export function ensureHex(s) {
6
+ const t = s.trim();
7
+ return t.startsWith('0x') ? t : '0x' + t;
8
+ }
9
+ /** Encode bytes to hex with 0x prefix. */
10
+ export function bytesToHex(bytes) {
11
+ return '0x' + Array.from(bytes)
12
+ .map((b) => b.toString(16).padStart(2, '0'))
13
+ .join('');
14
+ }
15
+ const HEX_RE = /^[0-9a-fA-F]+$/;
16
+ /** Decode hex string to bytes (with or without 0x). */
17
+ export function hexToBytes(hex) {
18
+ const raw = hex.trimStart().replace(/^0x/i, '');
19
+ if (raw.length % 2 !== 0)
20
+ throw new Error('Invalid hex: length must be even');
21
+ if (!HEX_RE.test(raw))
22
+ throw new Error('Invalid hex: expected 0-9, a-f, A-F');
23
+ const bytes = new Uint8Array(raw.length / 2);
24
+ for (let i = 0; i < bytes.length; i++) {
25
+ bytes[i] = parseInt(raw.slice(i * 2, i * 2 + 2), 16);
26
+ }
27
+ return bytes;
28
+ }
29
+ /**
30
+ * Normalize hex and require exactly 32 bytes (64 hex chars). Use for account IDs and hashes.
31
+ * @returns Hex string with 0x prefix
32
+ * @throws if not valid hex or length is not 64
33
+ */
34
+ export function validateHex32(hex) {
35
+ const normalized = ensureHex(hex);
36
+ const raw = normalized.slice(2);
37
+ if (raw.length !== 64)
38
+ throw new Error(`Expected 32 bytes (64 hex chars), got ${raw.length} hex chars`);
39
+ if (!HEX_RE.test(raw))
40
+ throw new Error('Invalid hex: expected 0-9, a-f, A-F');
41
+ return normalized;
42
+ }
43
+ /**
44
+ * Decode a **32-byte** `boing_getContractStorage` **value** word as a Boing **`AccountId`**, or **`null`**
45
+ * if the word is all zero. Truncates/pads to 64 hex chars like other storage decoders.
46
+ */
47
+ export function decodeBoingStorageWordAccountId(valueHex) {
48
+ const raw = ensureHex(valueHex).slice(2).toLowerCase();
49
+ if (raw.length % 2 !== 0) {
50
+ throw new Error('storage word AccountId: hex length must be even');
51
+ }
52
+ if (!HEX_RE.test(raw)) {
53
+ throw new Error('storage word AccountId: invalid hex');
54
+ }
55
+ const word64 = raw.length > 64 ? raw.slice(-64) : raw.padStart(64, '0');
56
+ if (word64 === '0'.repeat(64))
57
+ return null;
58
+ return validateHex32(`0x${word64}`);
59
+ }
60
+ /** True if **`hex`** is a valid **32-byte** Boing **`AccountId`** (`0x` + 64 hex). Use to branch wizards away from 20-byte EVM addresses. */
61
+ export function isBoingNativeAccountIdHex(hex) {
62
+ try {
63
+ validateHex32(hex);
64
+ return true;
65
+ }
66
+ catch {
67
+ return false;
68
+ }
69
+ }
70
+ /** Assert 32-byte buffer; return as hex. */
71
+ export function accountIdToHex(bytes) {
72
+ if (bytes.length !== 32)
73
+ throw new Error('AccountId must be 32 bytes');
74
+ return bytesToHex(bytes);
75
+ }
76
+ /** Parse 32-byte AccountId from hex. */
77
+ export function hexToAccountId(hex) {
78
+ const bytes = hexToBytes(hex);
79
+ if (bytes.length !== 32)
80
+ throw new Error('AccountId must be 32 bytes hex');
81
+ return bytes;
82
+ }