@0xkey-io/core 0.1.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 (183) hide show
  1. package/LICENSE +201 -0
  2. package/README.MD +7 -0
  3. package/dist/0xkey-helpers.d.ts +68 -0
  4. package/dist/0xkey-helpers.d.ts.map +1 -0
  5. package/dist/0xkey-helpers.js +466 -0
  6. package/dist/0xkey-helpers.js.map +1 -0
  7. package/dist/0xkey-helpers.mjs +399 -0
  8. package/dist/0xkey-helpers.mjs.map +1 -0
  9. package/dist/__clients__/core.d.ts +1201 -0
  10. package/dist/__clients__/core.d.ts.map +1 -0
  11. package/dist/__clients__/core.js +3489 -0
  12. package/dist/__clients__/core.js.map +1 -0
  13. package/dist/__clients__/core.mjs +3487 -0
  14. package/dist/__clients__/core.mjs.map +1 -0
  15. package/dist/__generated__/sdk-client-base.d.ts +281 -0
  16. package/dist/__generated__/sdk-client-base.d.ts.map +1 -0
  17. package/dist/__generated__/sdk-client-base.js +3906 -0
  18. package/dist/__generated__/sdk-client-base.js.map +1 -0
  19. package/dist/__generated__/sdk-client-base.mjs +3904 -0
  20. package/dist/__generated__/sdk-client-base.mjs.map +1 -0
  21. package/dist/__generated__/version.d.ts +2 -0
  22. package/dist/__generated__/version.d.ts.map +1 -0
  23. package/dist/__generated__/version.js +6 -0
  24. package/dist/__generated__/version.js.map +1 -0
  25. package/dist/__generated__/version.mjs +4 -0
  26. package/dist/__generated__/version.mjs.map +1 -0
  27. package/dist/__inputs__/public_api.types.d.ts +6014 -0
  28. package/dist/__inputs__/public_api.types.d.ts.map +1 -0
  29. package/dist/__polyfills__/jest.setup.webcrypto.d.ts +2 -0
  30. package/dist/__polyfills__/jest.setup.webcrypto.d.ts.map +1 -0
  31. package/dist/__polyfills__/window.d.ts +15 -0
  32. package/dist/__polyfills__/window.d.ts.map +1 -0
  33. package/dist/__polyfills__/window.js +30 -0
  34. package/dist/__polyfills__/window.js.map +1 -0
  35. package/dist/__polyfills__/window.mjs +28 -0
  36. package/dist/__polyfills__/window.mjs.map +1 -0
  37. package/dist/__stampers__/api/base.d.ts +27 -0
  38. package/dist/__stampers__/api/base.d.ts.map +1 -0
  39. package/dist/__stampers__/api/base.js +102 -0
  40. package/dist/__stampers__/api/base.js.map +1 -0
  41. package/dist/__stampers__/api/base.mjs +100 -0
  42. package/dist/__stampers__/api/base.mjs.map +1 -0
  43. package/dist/__stampers__/api/mobile/stamper.d.ts +15 -0
  44. package/dist/__stampers__/api/mobile/stamper.d.ts.map +1 -0
  45. package/dist/__stampers__/api/mobile/stamper.js +119 -0
  46. package/dist/__stampers__/api/mobile/stamper.js.map +1 -0
  47. package/dist/__stampers__/api/mobile/stamper.mjs +117 -0
  48. package/dist/__stampers__/api/mobile/stamper.mjs.map +1 -0
  49. package/dist/__stampers__/api/web/stamper.d.ts +14 -0
  50. package/dist/__stampers__/api/web/stamper.d.ts.map +1 -0
  51. package/dist/__stampers__/api/web/stamper.js +201 -0
  52. package/dist/__stampers__/api/web/stamper.js.map +1 -0
  53. package/dist/__stampers__/api/web/stamper.mjs +199 -0
  54. package/dist/__stampers__/api/web/stamper.mjs.map +1 -0
  55. package/dist/__stampers__/passkey/base.d.ts +16 -0
  56. package/dist/__stampers__/passkey/base.d.ts.map +1 -0
  57. package/dist/__stampers__/passkey/base.js +138 -0
  58. package/dist/__stampers__/passkey/base.js.map +1 -0
  59. package/dist/__stampers__/passkey/base.mjs +134 -0
  60. package/dist/__stampers__/passkey/base.mjs.map +1 -0
  61. package/dist/__storage__/base.d.ts +3 -0
  62. package/dist/__storage__/base.d.ts.map +1 -0
  63. package/dist/__storage__/base.js +27 -0
  64. package/dist/__storage__/base.js.map +1 -0
  65. package/dist/__storage__/base.mjs +25 -0
  66. package/dist/__storage__/base.mjs.map +1 -0
  67. package/dist/__storage__/mobile/storage.d.ts +18 -0
  68. package/dist/__storage__/mobile/storage.d.ts.map +1 -0
  69. package/dist/__storage__/mobile/storage.js +76 -0
  70. package/dist/__storage__/mobile/storage.js.map +1 -0
  71. package/dist/__storage__/mobile/storage.mjs +74 -0
  72. package/dist/__storage__/mobile/storage.mjs.map +1 -0
  73. package/dist/__storage__/web/storage.d.ts +19 -0
  74. package/dist/__storage__/web/storage.d.ts.map +1 -0
  75. package/dist/__storage__/web/storage.js +79 -0
  76. package/dist/__storage__/web/storage.js.map +1 -0
  77. package/dist/__storage__/web/storage.mjs +77 -0
  78. package/dist/__storage__/web/storage.mjs.map +1 -0
  79. package/dist/__typedoc-entry__/index.d.ts +3 -0
  80. package/dist/__typedoc-entry__/index.d.ts.map +1 -0
  81. package/dist/__types__/auth.d.ts +120 -0
  82. package/dist/__types__/auth.d.ts.map +1 -0
  83. package/dist/__types__/auth.js +7 -0
  84. package/dist/__types__/auth.js.map +1 -0
  85. package/dist/__types__/auth.mjs +5 -0
  86. package/dist/__types__/auth.mjs.map +1 -0
  87. package/dist/__types__/config.d.ts +145 -0
  88. package/dist/__types__/config.d.ts.map +1 -0
  89. package/dist/__types__/enums.d.ts +59 -0
  90. package/dist/__types__/enums.d.ts.map +1 -0
  91. package/dist/__types__/enums.js +72 -0
  92. package/dist/__types__/enums.js.map +1 -0
  93. package/dist/__types__/enums.mjs +70 -0
  94. package/dist/__types__/enums.mjs.map +1 -0
  95. package/dist/__types__/error.d.ts +13 -0
  96. package/dist/__types__/error.d.ts.map +1 -0
  97. package/dist/__types__/error.js +18 -0
  98. package/dist/__types__/error.js.map +1 -0
  99. package/dist/__types__/error.mjs +16 -0
  100. package/dist/__types__/error.mjs.map +1 -0
  101. package/dist/__types__/export.d.ts +10 -0
  102. package/dist/__types__/export.d.ts.map +1 -0
  103. package/dist/__types__/external-wallets.d.ts +203 -0
  104. package/dist/__types__/external-wallets.d.ts.map +1 -0
  105. package/dist/__types__/http.d.ts +17 -0
  106. package/dist/__types__/http.d.ts.map +1 -0
  107. package/dist/__types__/http.js +11 -0
  108. package/dist/__types__/http.js.map +1 -0
  109. package/dist/__types__/http.mjs +9 -0
  110. package/dist/__types__/http.mjs.map +1 -0
  111. package/dist/__types__/index.d.ts +10 -0
  112. package/dist/__types__/index.d.ts.map +1 -0
  113. package/dist/__types__/method-types/import-export-params.d.ts +38 -0
  114. package/dist/__types__/method-types/import-export-params.d.ts.map +1 -0
  115. package/dist/__types__/method-types/shared.d.ts +378 -0
  116. package/dist/__types__/method-types/shared.d.ts.map +1 -0
  117. package/dist/__wallet__/base.d.ts +14 -0
  118. package/dist/__wallet__/base.d.ts.map +1 -0
  119. package/dist/__wallet__/base.js +35 -0
  120. package/dist/__wallet__/base.js.map +1 -0
  121. package/dist/__wallet__/base.mjs +33 -0
  122. package/dist/__wallet__/base.mjs.map +1 -0
  123. package/dist/__wallet__/connector.d.ts +60 -0
  124. package/dist/__wallet__/connector.d.ts.map +1 -0
  125. package/dist/__wallet__/connector.js +93 -0
  126. package/dist/__wallet__/connector.js.map +1 -0
  127. package/dist/__wallet__/connector.mjs +91 -0
  128. package/dist/__wallet__/connector.mjs.map +1 -0
  129. package/dist/__wallet__/mobile/manager.d.ts +51 -0
  130. package/dist/__wallet__/mobile/manager.d.ts.map +1 -0
  131. package/dist/__wallet__/mobile/manager.js +115 -0
  132. package/dist/__wallet__/mobile/manager.js.map +1 -0
  133. package/dist/__wallet__/mobile/manager.mjs +113 -0
  134. package/dist/__wallet__/mobile/manager.mjs.map +1 -0
  135. package/dist/__wallet__/stamper.d.ts +90 -0
  136. package/dist/__wallet__/stamper.d.ts.map +1 -0
  137. package/dist/__wallet__/stamper.js +183 -0
  138. package/dist/__wallet__/stamper.js.map +1 -0
  139. package/dist/__wallet__/stamper.mjs +180 -0
  140. package/dist/__wallet__/stamper.mjs.map +1 -0
  141. package/dist/__wallet__/wallet-connect/base.d.ts +182 -0
  142. package/dist/__wallet__/wallet-connect/base.d.ts.map +1 -0
  143. package/dist/__wallet__/wallet-connect/base.js +606 -0
  144. package/dist/__wallet__/wallet-connect/base.js.map +1 -0
  145. package/dist/__wallet__/wallet-connect/base.mjs +604 -0
  146. package/dist/__wallet__/wallet-connect/base.mjs.map +1 -0
  147. package/dist/__wallet__/wallet-connect/client.d.ts +132 -0
  148. package/dist/__wallet__/wallet-connect/client.d.ts.map +1 -0
  149. package/dist/__wallet__/wallet-connect/client.js +262 -0
  150. package/dist/__wallet__/wallet-connect/client.js.map +1 -0
  151. package/dist/__wallet__/wallet-connect/client.mjs +260 -0
  152. package/dist/__wallet__/wallet-connect/client.mjs.map +1 -0
  153. package/dist/__wallet__/web/manager.d.ts +70 -0
  154. package/dist/__wallet__/web/manager.d.ts.map +1 -0
  155. package/dist/__wallet__/web/manager.js +177 -0
  156. package/dist/__wallet__/web/manager.js.map +1 -0
  157. package/dist/__wallet__/web/manager.mjs +175 -0
  158. package/dist/__wallet__/web/manager.mjs.map +1 -0
  159. package/dist/__wallet__/web/native/ethereum.d.ts +101 -0
  160. package/dist/__wallet__/web/native/ethereum.d.ts.map +1 -0
  161. package/dist/__wallet__/web/native/ethereum.js +339 -0
  162. package/dist/__wallet__/web/native/ethereum.js.map +1 -0
  163. package/dist/__wallet__/web/native/ethereum.mjs +336 -0
  164. package/dist/__wallet__/web/native/ethereum.mjs.map +1 -0
  165. package/dist/__wallet__/web/native/solana.d.ts +72 -0
  166. package/dist/__wallet__/web/native/solana.d.ts.map +1 -0
  167. package/dist/__wallet__/web/native/solana.js +215 -0
  168. package/dist/__wallet__/web/native/solana.js.map +1 -0
  169. package/dist/__wallet__/web/native/solana.mjs +212 -0
  170. package/dist/__wallet__/web/native/solana.mjs.map +1 -0
  171. package/dist/index.d.ts +19 -0
  172. package/dist/index.d.ts.map +1 -0
  173. package/dist/index.js +83 -0
  174. package/dist/index.js.map +1 -0
  175. package/dist/index.mjs +10 -0
  176. package/dist/index.mjs.map +1 -0
  177. package/dist/utils.d.ts +160 -0
  178. package/dist/utils.d.ts.map +1 -0
  179. package/dist/utils.js +1047 -0
  180. package/dist/utils.js.map +1 -0
  181. package/dist/utils.mjs +1007 -0
  182. package/dist/utils.mjs.map +1 -0
  183. package/package.json +80 -0
package/dist/utils.mjs ADDED
@@ -0,0 +1,1007 @@
1
+ import { ZeroXKeyErrorCodes, ZeroXKeyError, ZeroXKeyNetworkError } from '@0xkey-io/sdk-types';
2
+ import { Chain, Curve, WalletSource, StamperType } from './__types__/enums.mjs';
3
+ import { ZeroXKeyRequestError } from './__types__/error.mjs';
4
+ import { decodeBase64urlToString, uint8ArrayFromHexString, uint8ArrayToHexString, bs58 } from '@0xkey-io/encoding';
5
+ import { DEFAULT_XRP_ACCOUNTS, DEFAULT_TON_V4R2_ACCOUNTS, DEFAULT_TON_V3R2_ACCOUNTS, DEFAULT_DOGE_TESTNET_ACCOUNTS, DEFAULT_DOGE_MAINNET_ACCOUNTS, DEFAULT_XLM_ACCOUNTS, DEFAULT_SEI_ACCOUNTS, DEFAULT_BITCOIN_REGTEST_P2TR_ACCOUNTS, DEFAULT_BITCOIN_REGTEST_P2WSH_ACCOUNTS, DEFAULT_BITCOIN_REGTEST_P2WPKH_ACCOUNTS, DEFAULT_BITCOIN_REGTEST_P2SH_ACCOUNTS, DEFAULT_BITCOIN_REGTEST_P2PKH_ACCOUNTS, DEFAULT_BITCOIN_SIGNET_P2TR_ACCOUNTS, DEFAULT_BITCOIN_SIGNET_P2WSH_ACCOUNTS, DEFAULT_BITCOIN_SIGNET_P2WPKH_ACCOUNTS, DEFAULT_BITCOIN_SIGNET_P2SH_ACCOUNTS, DEFAULT_BITCOIN_SIGNET_P2PKH_ACCOUNTS, DEFAULT_BITCOIN_TESTNET_P2TR_ACCOUNTS, DEFAULT_BITCOIN_TESTNET_P2WSH_ACCOUNTS, DEFAULT_BITCOIN_TESTNET_P2WPKH_ACCOUNTS, DEFAULT_BITCOIN_TESTNET_P2SH_ACCOUNTS, DEFAULT_BITCOIN_TESTNET_P2PKH_ACCOUNTS, DEFAULT_BITCOIN_MAINNET_P2TR_ACCOUNTS, DEFAULT_BITCOIN_MAINNET_P2WSH_ACCOUNTS, DEFAULT_BITCOIN_MAINNET_P2WPKH_ACCOUNTS, DEFAULT_BITCOIN_MAINNET_P2SH_ACCOUNTS, DEFAULT_BITCOIN_MAINNET_P2PKH_ACCOUNTS, DEFAULT_APTOS_ACCOUNTS, DEFAULT_SUI_ACCOUNTS, DEFAULT_TRON_ACCOUNTS, DEFAULT_COSMOS_ACCOUNTS, DEFAULT_SOLANA_ACCOUNTS, DEFAULT_ETHEREUM_ACCOUNTS } from './0xkey-helpers.mjs';
6
+ import { uncompressRawPublicKey, fromDerSignature } from '@0xkey-io/crypto';
7
+ import { keccak256, toUtf8String } from 'ethers';
8
+ import { VERSION } from './__generated__/version.mjs';
9
+
10
+ /**
11
+ * Configuration for all supported address formats.
12
+ *
13
+ * Includes:
14
+ * - encoding type
15
+ * - hash function
16
+ * - default accounts for the address format
17
+ * - display name for the address format
18
+ *
19
+ * ```ts
20
+ * // Example usage:
21
+ * import { addressFormatConfig } from "@0xkey-io/sdk-core";
22
+ *
23
+ * const config = addressFormatConfig["ADDRESS_FORMAT_ETHEREUM"];
24
+ * ```
25
+ */
26
+ const sessionExpiredErrors = {
27
+ pubKeyNotFound: "could not find public key in organization or its parent organization",
28
+ apiKeyExpired: "Unauthenticated desc = expired api key publicKey",
29
+ };
30
+ // Global errors to match against error messages returned from the API
31
+ const globalErrorsToMatch = Object.freeze({
32
+ [sessionExpiredErrors.pubKeyNotFound]: {
33
+ message: "Session public key could not be found in the sub-organization or parent organization",
34
+ code: ZeroXKeyErrorCodes.SESSION_EXPIRED,
35
+ },
36
+ [sessionExpiredErrors.apiKeyExpired]: {
37
+ message: "Session API key has expired",
38
+ code: ZeroXKeyErrorCodes.SESSION_EXPIRED,
39
+ },
40
+ });
41
+ const addressFormatConfig = {
42
+ ADDRESS_FORMAT_UNCOMPRESSED: {
43
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
44
+ hashFunction: "HASH_FUNCTION_SHA256",
45
+ defaultAccounts: null,
46
+ displayName: "Uncompressed",
47
+ },
48
+ ADDRESS_FORMAT_COMPRESSED: {
49
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
50
+ hashFunction: "HASH_FUNCTION_SHA256",
51
+ defaultAccounts: null,
52
+ displayName: "Compressed",
53
+ },
54
+ ADDRESS_FORMAT_ETHEREUM: {
55
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
56
+ hashFunction: "HASH_FUNCTION_KECCAK256",
57
+ defaultAccounts: DEFAULT_ETHEREUM_ACCOUNTS,
58
+ displayName: "Ethereum",
59
+ },
60
+ ADDRESS_FORMAT_SOLANA: {
61
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
62
+ hashFunction: "HASH_FUNCTION_NOT_APPLICABLE",
63
+ defaultAccounts: DEFAULT_SOLANA_ACCOUNTS,
64
+ displayName: "Solana",
65
+ },
66
+ ADDRESS_FORMAT_COSMOS: {
67
+ encoding: "PAYLOAD_ENCODING_TEXT_UTF8",
68
+ hashFunction: "HASH_FUNCTION_SHA256",
69
+ defaultAccounts: DEFAULT_COSMOS_ACCOUNTS,
70
+ displayName: "Cosmos",
71
+ },
72
+ ADDRESS_FORMAT_TRON: {
73
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
74
+ hashFunction: "HASH_FUNCTION_SHA256",
75
+ defaultAccounts: DEFAULT_TRON_ACCOUNTS,
76
+ displayName: "Tron",
77
+ },
78
+ ADDRESS_FORMAT_SUI: {
79
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
80
+ hashFunction: "HASH_FUNCTION_NOT_APPLICABLE",
81
+ defaultAccounts: DEFAULT_SUI_ACCOUNTS,
82
+ displayName: "Sui",
83
+ },
84
+ ADDRESS_FORMAT_APTOS: {
85
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
86
+ hashFunction: "HASH_FUNCTION_NOT_APPLICABLE",
87
+ defaultAccounts: DEFAULT_APTOS_ACCOUNTS,
88
+ displayName: "Aptos",
89
+ },
90
+ ADDRESS_FORMAT_BITCOIN_MAINNET_P2PKH: {
91
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
92
+ hashFunction: "HASH_FUNCTION_SHA256",
93
+ defaultAccounts: DEFAULT_BITCOIN_MAINNET_P2PKH_ACCOUNTS,
94
+ displayName: "Bitcoin Mainnet P2PKH",
95
+ },
96
+ ADDRESS_FORMAT_BITCOIN_MAINNET_P2SH: {
97
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
98
+ hashFunction: "HASH_FUNCTION_SHA256",
99
+ defaultAccounts: DEFAULT_BITCOIN_MAINNET_P2SH_ACCOUNTS,
100
+ displayName: "Bitcoin Mainnet P2SH",
101
+ },
102
+ ADDRESS_FORMAT_BITCOIN_MAINNET_P2WPKH: {
103
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
104
+ hashFunction: "HASH_FUNCTION_SHA256",
105
+ defaultAccounts: DEFAULT_BITCOIN_MAINNET_P2WPKH_ACCOUNTS,
106
+ displayName: "Bitcoin Mainnet P2WPKH",
107
+ },
108
+ ADDRESS_FORMAT_BITCOIN_MAINNET_P2WSH: {
109
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
110
+ hashFunction: "HASH_FUNCTION_SHA256",
111
+ defaultAccounts: DEFAULT_BITCOIN_MAINNET_P2WSH_ACCOUNTS,
112
+ displayName: "Bitcoin Mainnet P2WSH",
113
+ },
114
+ ADDRESS_FORMAT_BITCOIN_MAINNET_P2TR: {
115
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
116
+ hashFunction: "HASH_FUNCTION_SHA256",
117
+ defaultAccounts: DEFAULT_BITCOIN_MAINNET_P2TR_ACCOUNTS,
118
+ displayName: "Bitcoin Mainnet P2TR",
119
+ },
120
+ ADDRESS_FORMAT_BITCOIN_TESTNET_P2PKH: {
121
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
122
+ hashFunction: "HASH_FUNCTION_SHA256",
123
+ defaultAccounts: DEFAULT_BITCOIN_TESTNET_P2PKH_ACCOUNTS,
124
+ displayName: "Bitcoin Testnet P2PKH",
125
+ },
126
+ ADDRESS_FORMAT_BITCOIN_TESTNET_P2SH: {
127
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
128
+ hashFunction: "HASH_FUNCTION_SHA256",
129
+ defaultAccounts: DEFAULT_BITCOIN_TESTNET_P2SH_ACCOUNTS,
130
+ displayName: "Bitcoin Testnet P2SH",
131
+ },
132
+ ADDRESS_FORMAT_BITCOIN_TESTNET_P2WPKH: {
133
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
134
+ hashFunction: "HASH_FUNCTION_SHA256",
135
+ defaultAccounts: DEFAULT_BITCOIN_TESTNET_P2WPKH_ACCOUNTS,
136
+ displayName: "Bitcoin Testnet P2WPKH",
137
+ },
138
+ ADDRESS_FORMAT_BITCOIN_TESTNET_P2WSH: {
139
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
140
+ hashFunction: "HASH_FUNCTION_SHA256",
141
+ defaultAccounts: DEFAULT_BITCOIN_TESTNET_P2WSH_ACCOUNTS,
142
+ displayName: "Bitcoin Testnet P2WSH",
143
+ },
144
+ ADDRESS_FORMAT_BITCOIN_TESTNET_P2TR: {
145
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
146
+ hashFunction: "HASH_FUNCTION_SHA256",
147
+ defaultAccounts: DEFAULT_BITCOIN_TESTNET_P2TR_ACCOUNTS,
148
+ displayName: "Bitcoin Testnet P2TR",
149
+ },
150
+ ADDRESS_FORMAT_BITCOIN_SIGNET_P2PKH: {
151
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
152
+ hashFunction: "HASH_FUNCTION_SHA256",
153
+ defaultAccounts: DEFAULT_BITCOIN_SIGNET_P2PKH_ACCOUNTS,
154
+ displayName: "Bitcoin Signet P2PKH",
155
+ },
156
+ ADDRESS_FORMAT_BITCOIN_SIGNET_P2SH: {
157
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
158
+ hashFunction: "HASH_FUNCTION_SHA256",
159
+ defaultAccounts: DEFAULT_BITCOIN_SIGNET_P2SH_ACCOUNTS,
160
+ displayName: "Bitcoin Signet P2SH",
161
+ },
162
+ ADDRESS_FORMAT_BITCOIN_SIGNET_P2WPKH: {
163
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
164
+ hashFunction: "HASH_FUNCTION_SHA256",
165
+ defaultAccounts: DEFAULT_BITCOIN_SIGNET_P2WPKH_ACCOUNTS,
166
+ displayName: "Bitcoin Signet P2WPKH",
167
+ },
168
+ ADDRESS_FORMAT_BITCOIN_SIGNET_P2WSH: {
169
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
170
+ hashFunction: "HASH_FUNCTION_SHA256",
171
+ defaultAccounts: DEFAULT_BITCOIN_SIGNET_P2WSH_ACCOUNTS,
172
+ displayName: "Bitcoin Signet P2WSH",
173
+ },
174
+ ADDRESS_FORMAT_BITCOIN_SIGNET_P2TR: {
175
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
176
+ hashFunction: "HASH_FUNCTION_SHA256",
177
+ defaultAccounts: DEFAULT_BITCOIN_SIGNET_P2TR_ACCOUNTS,
178
+ displayName: "Bitcoin Signet P2TR",
179
+ },
180
+ ADDRESS_FORMAT_BITCOIN_REGTEST_P2PKH: {
181
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
182
+ hashFunction: "HASH_FUNCTION_SHA256",
183
+ defaultAccounts: DEFAULT_BITCOIN_REGTEST_P2PKH_ACCOUNTS,
184
+ displayName: "Bitcoin Regtest P2PKH",
185
+ },
186
+ ADDRESS_FORMAT_BITCOIN_REGTEST_P2SH: {
187
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
188
+ hashFunction: "HASH_FUNCTION_SHA256",
189
+ defaultAccounts: DEFAULT_BITCOIN_REGTEST_P2SH_ACCOUNTS,
190
+ displayName: "Bitcoin Regtest P2SH",
191
+ },
192
+ ADDRESS_FORMAT_BITCOIN_REGTEST_P2WPKH: {
193
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
194
+ hashFunction: "HASH_FUNCTION_SHA256",
195
+ defaultAccounts: DEFAULT_BITCOIN_REGTEST_P2WPKH_ACCOUNTS,
196
+ displayName: "Bitcoin Regtest P2WPKH",
197
+ },
198
+ ADDRESS_FORMAT_BITCOIN_REGTEST_P2WSH: {
199
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
200
+ hashFunction: "HASH_FUNCTION_SHA256",
201
+ defaultAccounts: DEFAULT_BITCOIN_REGTEST_P2WSH_ACCOUNTS,
202
+ displayName: "Bitcoin Regtest P2WSH",
203
+ },
204
+ ADDRESS_FORMAT_BITCOIN_REGTEST_P2TR: {
205
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
206
+ hashFunction: "HASH_FUNCTION_SHA256",
207
+ defaultAccounts: DEFAULT_BITCOIN_REGTEST_P2TR_ACCOUNTS,
208
+ displayName: "Bitcoin Regtest P2TR",
209
+ },
210
+ ADDRESS_FORMAT_SEI: {
211
+ encoding: "PAYLOAD_ENCODING_TEXT_UTF8",
212
+ hashFunction: "HASH_FUNCTION_SHA256",
213
+ defaultAccounts: DEFAULT_SEI_ACCOUNTS,
214
+ displayName: "Sei",
215
+ },
216
+ ADDRESS_FORMAT_XLM: {
217
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
218
+ hashFunction: "HASH_FUNCTION_NOT_APPLICABLE",
219
+ defaultAccounts: DEFAULT_XLM_ACCOUNTS,
220
+ displayName: "Xlm",
221
+ },
222
+ ADDRESS_FORMAT_DOGE_MAINNET: {
223
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
224
+ hashFunction: "HASH_FUNCTION_SHA256",
225
+ defaultAccounts: DEFAULT_DOGE_MAINNET_ACCOUNTS,
226
+ displayName: "Doge Mainnet",
227
+ },
228
+ ADDRESS_FORMAT_DOGE_TESTNET: {
229
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
230
+ hashFunction: "HASH_FUNCTION_SHA256",
231
+ defaultAccounts: DEFAULT_DOGE_TESTNET_ACCOUNTS,
232
+ displayName: "Doge Testnet",
233
+ },
234
+ ADDRESS_FORMAT_TON_V3R2: {
235
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
236
+ hashFunction: "HASH_FUNCTION_NOT_APPLICABLE",
237
+ defaultAccounts: DEFAULT_TON_V3R2_ACCOUNTS,
238
+ displayName: "Ton V3R2",
239
+ },
240
+ ADDRESS_FORMAT_TON_V4R2: {
241
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
242
+ hashFunction: "HASH_FUNCTION_NOT_APPLICABLE",
243
+ defaultAccounts: DEFAULT_TON_V4R2_ACCOUNTS,
244
+ displayName: "Ton V4R2",
245
+ },
246
+ ADDRESS_FORMAT_TON_V5R1: {
247
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
248
+ hashFunction: "HASH_FUNCTION_NOT_APPLICABLE",
249
+ defaultAccounts: null,
250
+ displayName: "Ton V5R1",
251
+ },
252
+ ADDRESS_FORMAT_XRP: {
253
+ encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
254
+ hashFunction: "HASH_FUNCTION_SHA256",
255
+ defaultAccounts: DEFAULT_XRP_ACCOUNTS,
256
+ displayName: "XRP",
257
+ },
258
+ };
259
+ const googleISS = "https://accounts.google.com";
260
+ const isReactNative = () => {
261
+ const g = typeof globalThis !== "undefined" ? globalThis : global;
262
+ // if we have a DOM, it's definitely not RN
263
+ // RN-web has DOM but we want false for that anyway
264
+ if (typeof document !== "undefined" && typeof window !== "undefined")
265
+ return false;
266
+ // check for RN-specific globals
267
+ // these shouldn't exist in Node, browsers, or webviews
268
+ return (typeof g?.__fbBatchedBridge !== "undefined" ||
269
+ typeof g?.nativeCallSyncHook !== "undefined" ||
270
+ typeof g?.RN$Bridgeless !== "undefined");
271
+ };
272
+ const isWeb = () => {
273
+ return typeof window !== "undefined" && typeof document !== "undefined";
274
+ };
275
+ const generateRandomBuffer = () => {
276
+ const arr = new Uint8Array(32);
277
+ crypto.getRandomValues(arr);
278
+ return arr.buffer;
279
+ };
280
+ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
281
+ const toExternalTimestamp = (date = new Date()) => {
282
+ const millis = date.getTime();
283
+ const seconds = Math.floor(millis / 1000);
284
+ const nanos = (millis % 1000) * 1_000_000;
285
+ return {
286
+ seconds: seconds.toString(),
287
+ nanos: nanos.toString(),
288
+ };
289
+ };
290
+ async function getActiveSessionOrThrowIfRequired(stampWith, getActiveSession) {
291
+ const session = await getActiveSession();
292
+ // the api-key stamper requires an active session
293
+ // if there is no stampWith defined, the default is api-key stamper
294
+ if ((!stampWith || stampWith === StamperType.ApiKey) && !session) {
295
+ throw new ZeroXKeyError("No active session found. Please log in first.", ZeroXKeyErrorCodes.NO_SESSION_FOUND);
296
+ }
297
+ return session;
298
+ }
299
+ function parseSession(token) {
300
+ if (typeof token !== "string") {
301
+ return token;
302
+ }
303
+ const [, payload] = token.split(".");
304
+ if (!payload) {
305
+ throw new Error("Invalid JWT: Missing payload");
306
+ }
307
+ const decoded = JSON.parse(atob(payload));
308
+ const { exp, public_key: publicKey, session_type: sessionType, user_id: userId, organization_id: organizationId, } = decoded;
309
+ if (!exp || !publicKey || !sessionType || !userId || !organizationId) {
310
+ throw new Error("JWT payload missing required fields");
311
+ }
312
+ const expSeconds = Math.ceil((exp * 1000 - Date.now()) / 1000);
313
+ return {
314
+ sessionType,
315
+ userId,
316
+ organizationId,
317
+ expiry: exp,
318
+ expirationSeconds: expSeconds.toString(),
319
+ publicKey,
320
+ token,
321
+ };
322
+ }
323
+ function getHashFunction(addressFormat) {
324
+ const config = addressFormatConfig[addressFormat];
325
+ if (!config) {
326
+ throw new ZeroXKeyError(`Unsupported address format: ${addressFormat}`, ZeroXKeyErrorCodes.INVALID_REQUEST);
327
+ }
328
+ return config.hashFunction;
329
+ }
330
+ function getEncodingType(addressFormat) {
331
+ const config = addressFormatConfig[addressFormat];
332
+ if (!config) {
333
+ throw new ZeroXKeyError(`Unsupported address format: ${addressFormat}`, ZeroXKeyErrorCodes.INVALID_REQUEST);
334
+ }
335
+ return config.encoding;
336
+ }
337
+ function getEncodedMessage(payloadEncoding, rawMessage) {
338
+ if (payloadEncoding === "PAYLOAD_ENCODING_HEXADECIMAL") {
339
+ return ("0x" +
340
+ Array.from(rawMessage)
341
+ .map((b) => b.toString(16).padStart(2, "0"))
342
+ .join(""));
343
+ }
344
+ // we decode back to a UTF-8 string
345
+ return toUtf8String(rawMessage);
346
+ }
347
+ function hexSignedTxToBase58(hex) {
348
+ const bytes = uint8ArrayFromHexString(hex);
349
+ return bs58.encode(bytes);
350
+ }
351
+ const broadcastTransaction = async (params) => {
352
+ const { signedTransaction, rpcUrl, transactionType } = params;
353
+ switch (transactionType) {
354
+ case "TRANSACTION_TYPE_SOLANA": {
355
+ const encodedTx = hexSignedTxToBase58(signedTransaction);
356
+ const response = await fetch(rpcUrl, {
357
+ method: "POST",
358
+ headers: { "Content-Type": "application/json" },
359
+ body: JSON.stringify({
360
+ jsonrpc: "2.0",
361
+ id: 1,
362
+ method: "sendTransaction",
363
+ params: [encodedTx, { encoding: "base58" }],
364
+ }),
365
+ });
366
+ const json = await response.json();
367
+ if (json.error) {
368
+ throw new ZeroXKeyError(`Solana RPC Error: ${json.error.message}`, ZeroXKeyErrorCodes.SIGN_AND_SEND_TRANSACTION_ERROR);
369
+ }
370
+ return json.result;
371
+ }
372
+ case "TRANSACTION_TYPE_ETHEREUM": {
373
+ const response = await fetch(rpcUrl, {
374
+ method: "POST",
375
+ headers: { "Content-Type": "application/json" },
376
+ body: JSON.stringify({
377
+ jsonrpc: "2.0",
378
+ id: 1,
379
+ method: "eth_sendRawTransaction",
380
+ params: [signedTransaction],
381
+ }),
382
+ });
383
+ const json = await response.json();
384
+ if (json.error) {
385
+ throw new ZeroXKeyError(`Ethereum RPC Error: ${json.error.message}`, ZeroXKeyErrorCodes.SIGN_AND_SEND_TRANSACTION_ERROR);
386
+ }
387
+ return json.result;
388
+ }
389
+ case "TRANSACTION_TYPE_TRON": {
390
+ const response = await fetch(`${rpcUrl}/wallet/broadcasthex`, {
391
+ method: "POST",
392
+ headers: { "Content-Type": "application/json" },
393
+ body: JSON.stringify({ transaction: signedTransaction }),
394
+ });
395
+ const json = await response.json();
396
+ if (!json.result) {
397
+ throw new ZeroXKeyError(`Tron RPC Error: ${json.message}`, ZeroXKeyErrorCodes.SIGN_AND_SEND_TRANSACTION_ERROR);
398
+ }
399
+ return json.txid;
400
+ }
401
+ default:
402
+ throw new ZeroXKeyError(`Unsupported transaction type for broadcasting: ${transactionType}`, ZeroXKeyErrorCodes.SIGN_AND_SEND_TRANSACTION_ERROR);
403
+ }
404
+ };
405
+ function splitSignature(signature, addressFormat) {
406
+ const hex = signature.replace(/^0x/, "");
407
+ if (addressFormat === "ADDRESS_FORMAT_ETHEREUM") {
408
+ // this is a ECDSA signature
409
+ if (hex.length === 130) {
410
+ const r = hex.slice(0, 64);
411
+ const s = hex.slice(64, 128);
412
+ const v = hex.slice(128, 130);
413
+ return { r, s, v };
414
+ }
415
+ // this is a DER-encoded signatures (e.g., Ledger)
416
+ const raw = fromDerSignature(hex);
417
+ const r = uint8ArrayToHexString(raw.slice(0, 32));
418
+ const s = uint8ArrayToHexString(raw.slice(32, 64));
419
+ // DER signatures do not have a v component
420
+ // so we return 00 to match what ZeroXKey does
421
+ const v = "00";
422
+ return { r, s, v };
423
+ }
424
+ if (addressFormat === "ADDRESS_FORMAT_SOLANA") {
425
+ if (hex.length !== 128) {
426
+ throw new Error(`Invalid Solana signature length: expected 64 bytes (128 hex), got ${hex.length}`);
427
+ }
428
+ // this is a Ed25519 signature
429
+ const r = hex.slice(0, 64);
430
+ const s = hex.slice(64, 128);
431
+ // solana signatures do not have a v component
432
+ // so we return 00 to match what ZeroXKey does
433
+ return { r, s, v: "00" };
434
+ }
435
+ throw new Error(`Unsupported address format or invalid signature length: ${hex.length}`);
436
+ }
437
+ // Type guard to check if accounts is WalletAccount[]
438
+ function isWalletAccountArray(arr) {
439
+ return (arr.length === 0 ||
440
+ (typeof arr[0] === "object" &&
441
+ "addressFormat" in arr[0] &&
442
+ "curve" in arr[0] &&
443
+ "path" in arr[0] &&
444
+ "pathFormat" in arr[0]));
445
+ }
446
+ function createWalletAccountFromAddressFormat(addressFormat) {
447
+ const walletAccount = addressFormatConfig[addressFormat]?.defaultAccounts;
448
+ if (!walletAccount) {
449
+ throw new Error(`Unsupported address format: ${addressFormat}`);
450
+ }
451
+ if (walletAccount[0]) {
452
+ return walletAccount[0];
453
+ }
454
+ throw new Error(`No default accounts defined for address format: ${addressFormat}`);
455
+ }
456
+ /**@internal */
457
+ function generateWalletAccountsFromAddressFormat(params) {
458
+ const { addresses, existingWalletAccounts } = params;
459
+ const pathMap = new Map();
460
+ // Build a lookup for max index per (addressFormat, basePath)
461
+ const maxIndexMap = new Map();
462
+ if (existingWalletAccounts && existingWalletAccounts.length > 0) {
463
+ for (const acc of existingWalletAccounts) {
464
+ // Normalize base path (remove account index)
465
+ const basePath = acc.path.replace(/^((?:[^\/]+\/){3})[^\/]+/, "$1");
466
+ const key = `${acc.addressFormat}:${basePath}`;
467
+ const idxSegment = acc.path.split("/")[3];
468
+ const idx = idxSegment ? parseInt(idxSegment.replace(/'/, ""), 10) : -1;
469
+ if (!isNaN(idx)) {
470
+ maxIndexMap.set(key, Math.max(maxIndexMap.get(key) ?? -1, idx));
471
+ }
472
+ }
473
+ }
474
+ return addresses.map((addressFormat) => {
475
+ const account = createWalletAccountFromAddressFormat(addressFormat);
476
+ const basePath = account.path.replace(/^((?:[^\/]+\/){3})[^\/]+/, "$1");
477
+ const key = `${addressFormat}:${basePath}`;
478
+ let nextIndex = 0;
479
+ if (maxIndexMap.has(key)) {
480
+ nextIndex = maxIndexMap.get(key) + 1;
481
+ maxIndexMap.set(key, nextIndex);
482
+ }
483
+ else if (pathMap.has(account.path)) {
484
+ nextIndex = pathMap.get(account.path);
485
+ }
486
+ const pathWithIndex = account.path.replace(/^((?:[^\/]*\/){3})(\d+)/, (_, prefix) => `${prefix}${nextIndex}`);
487
+ pathMap.set(account.path, nextIndex + 1);
488
+ return {
489
+ ...account,
490
+ path: pathWithIndex,
491
+ };
492
+ });
493
+ }
494
+ function buildSignUpBody(params) {
495
+ const { createSubOrgParams } = params;
496
+ const authenticatorName = isWeb()
497
+ ? `${window.location.hostname}-${Date.now()}`
498
+ : `passkey-${Date.now()}`;
499
+ let authenticators = [];
500
+ if (createSubOrgParams?.authenticators?.length) {
501
+ authenticators =
502
+ createSubOrgParams?.authenticators?.map((authenticator) => ({
503
+ authenticatorName: authenticator?.authenticatorName || authenticatorName,
504
+ challenge: authenticator.challenge,
505
+ attestation: authenticator.attestation,
506
+ })) || [];
507
+ }
508
+ let apiKeys = [];
509
+ if (createSubOrgParams?.apiKeys?.length) {
510
+ apiKeys = createSubOrgParams.apiKeys
511
+ .filter((apiKey) => apiKey.curveType !== undefined)
512
+ .map((apiKey) => ({
513
+ apiKeyName: apiKey.apiKeyName || `api-key-${Date.now()}`,
514
+ publicKey: apiKey.publicKey,
515
+ curveType: apiKey.curveType,
516
+ ...(apiKey?.expirationSeconds && {
517
+ expirationSeconds: apiKey.expirationSeconds,
518
+ }),
519
+ }));
520
+ }
521
+ return {
522
+ userName: createSubOrgParams?.userName ||
523
+ createSubOrgParams?.userEmail ||
524
+ `user-${Date.now()}`,
525
+ ...(createSubOrgParams?.userEmail && {
526
+ userEmail: createSubOrgParams?.userEmail,
527
+ }),
528
+ ...(createSubOrgParams?.authenticators?.length
529
+ ? {
530
+ authenticators,
531
+ }
532
+ : { authenticators: [] }),
533
+ ...(createSubOrgParams?.userPhoneNumber && {
534
+ userPhoneNumber: createSubOrgParams.userPhoneNumber,
535
+ }),
536
+ ...(createSubOrgParams?.userTag && {
537
+ userTag: createSubOrgParams?.userTag,
538
+ }),
539
+ organizationName: createSubOrgParams?.subOrgName || `sub-org-${Date.now()}`,
540
+ ...(createSubOrgParams?.verificationToken && {
541
+ verificationToken: createSubOrgParams?.verificationToken,
542
+ }),
543
+ ...(createSubOrgParams?.apiKeys?.length
544
+ ? {
545
+ apiKeys,
546
+ }
547
+ : { apiKeys: [] }),
548
+ ...(createSubOrgParams?.oauthProviders?.length
549
+ ? {
550
+ oauthProviders: createSubOrgParams.oauthProviders,
551
+ }
552
+ : { oauthProviders: [] }),
553
+ ...(createSubOrgParams?.customWallet && {
554
+ wallet: {
555
+ walletName: createSubOrgParams.customWallet.walletName,
556
+ accounts: createSubOrgParams.customWallet.walletAccounts,
557
+ },
558
+ }),
559
+ };
560
+ }
561
+ /**
562
+ * Extracts the public key from a ZeroXKey stamp header value.
563
+ * @param stampHeaderValue - The base64url encoded stamp header value
564
+ * @returns The public key as a hex string
565
+ */
566
+ function getPublicKeyFromStampHeader(stampHeaderValue) {
567
+ try {
568
+ // we decode the base64url string to get the JSON stamp
569
+ const stampJson = decodeBase64urlToString(stampHeaderValue);
570
+ // we parse the JSON to get the stamp object
571
+ const stamp = JSON.parse(stampJson);
572
+ return stamp.publicKey;
573
+ }
574
+ catch (error) {
575
+ throw new Error(`Failed to extract public key from stamp header: ${error instanceof Error ? error.message : String(error)}`);
576
+ }
577
+ }
578
+ /**@internal */
579
+ function getPolicySignature(policy) {
580
+ return JSON.stringify({
581
+ policyName: policy.policyName,
582
+ effect: policy.effect,
583
+ condition: policy.condition ?? null,
584
+ consensus: policy.consensus ?? null,
585
+ });
586
+ }
587
+ /**@internal */
588
+ function isEthereumProvider(provider) {
589
+ return provider.chainInfo.namespace === Chain.Ethereum;
590
+ }
591
+ /**@internal */
592
+ function isSolanaProvider(provider) {
593
+ return provider.chainInfo.namespace === Chain.Solana;
594
+ }
595
+ /** @internal */
596
+ function getCurveTypeFromProvider(provider) {
597
+ if (isEthereumProvider(provider)) {
598
+ return "API_KEY_CURVE_SECP256K1";
599
+ }
600
+ if (isSolanaProvider(provider)) {
601
+ return "API_KEY_CURVE_ED25519";
602
+ }
603
+ // we should never hit this case
604
+ // if we do then it means we added support for a new chain but missed updating this function
605
+ throw new Error(`Unsupported provider namespace: ${provider.chainInfo.namespace}. Expected Ethereum or Solana.`);
606
+ }
607
+ /** @internal */
608
+ function getSignatureSchemeFromProvider(provider) {
609
+ if (isEthereumProvider(provider)) {
610
+ return "SIGNATURE_SCHEME_TK_API_SECP256K1_EIP191";
611
+ }
612
+ if (isSolanaProvider(provider)) {
613
+ return "SIGNATURE_SCHEME_TK_API_ED25519";
614
+ }
615
+ // we should never hit this case
616
+ // if we do then it means we added support for a new chain but missed updating this function
617
+ throw new Error(`Unsupported provider namespace: ${provider.chainInfo.namespace}. Expected Ethereum or Solana.`);
618
+ }
619
+ /** @internal */
620
+ function findWalletProviderFromAddress(address, providers) {
621
+ for (const provider of providers) {
622
+ if (provider.connectedAddresses.includes(address)) {
623
+ return provider;
624
+ }
625
+ }
626
+ // no provider found for that address
627
+ return undefined;
628
+ }
629
+ /**
630
+ * Derives a wallet address from a given public key and chain.
631
+ *
632
+ * @param chain - "ethereum" or "solana"
633
+ * @param publicKey - The raw public key string (can be compressed or uncompressed)
634
+ * @returns The derived wallet address
635
+ */
636
+ function addressFromPublicKey(chain, publicKey) {
637
+ if (chain === Chain.Ethereum) {
638
+ const publicKeyBytes = uint8ArrayFromHexString(publicKey);
639
+ let uncompressedKey;
640
+ if (publicKeyBytes.length === 65 && publicKeyBytes[0] === 0x04) {
641
+ // it's already uncompressed so we just convert
642
+ // to hex without the 04 prefix
643
+ uncompressedKey = uint8ArrayToHexString(publicKeyBytes.slice(1));
644
+ }
645
+ else {
646
+ // it's compressed, so we need to uncompress it first
647
+ // then convert to hex without the 04 prefix
648
+ const publicKeyUncompressed = uncompressRawPublicKey(publicKeyBytes, Curve.SECP256K1);
649
+ uncompressedKey = uint8ArrayToHexString(publicKeyUncompressed.slice(1));
650
+ }
651
+ // hash with Keccak256 and take last 20 bytes
652
+ const hash = keccak256(uint8ArrayFromHexString(uncompressedKey));
653
+ return "0x" + hash.slice(-40);
654
+ }
655
+ if (chain === Chain.Solana) {
656
+ return bs58.encode(uint8ArrayFromHexString(publicKey));
657
+ }
658
+ throw new Error(`Unsupported chain: ${chain}`);
659
+ }
660
+ /**@internal */
661
+ function getAuthenticatorAddresses(user) {
662
+ const ethereum = [];
663
+ const solana = [];
664
+ for (const key of user.apiKeys) {
665
+ const { type, publicKey } = key.credential;
666
+ switch (type) {
667
+ case "CREDENTIAL_TYPE_API_KEY_SECP256K1":
668
+ ethereum.push(addressFromPublicKey(Chain.Ethereum, publicKey));
669
+ break;
670
+ case "CREDENTIAL_TYPE_API_KEY_ED25519":
671
+ solana.push(addressFromPublicKey(Chain.Solana, publicKey));
672
+ break;
673
+ }
674
+ }
675
+ return { ethereum, solana };
676
+ }
677
+ /**@internal */
678
+ async function getAuthProxyConfig(authProxyConfigId, authProxyUrl) {
679
+ const fullUrl = (authProxyUrl ?? "https://authproxy.0xkey.com") + "/v1/wallet_kit_config";
680
+ var headers = {
681
+ "Content-Type": "application/json",
682
+ "X-Auth-Proxy-Config-ID": authProxyConfigId,
683
+ };
684
+ const response = await fetch(fullUrl, {
685
+ method: "POST",
686
+ headers: headers,
687
+ });
688
+ if (!response.ok) {
689
+ let res;
690
+ try {
691
+ res = await response.json();
692
+ }
693
+ catch (_) {
694
+ throw new Error(`${response.status} ${response.statusText}`);
695
+ }
696
+ throw new ZeroXKeyRequestError(res);
697
+ }
698
+ const data = await response.json();
699
+ return data;
700
+ }
701
+ /**
702
+ * Submits a signed request to ZeroXKey.
703
+ *
704
+ * You can pass in the SignedRequest returned by any of the SDK's
705
+ * stamping methods (stampStampLogin, stampGetPolicies, etc.).
706
+ *
707
+ * @deprecated Use `httpClient.sendSignedRequest()` instead, which includes
708
+ * automatic activity polling and result extraction.
709
+ *
710
+ * @param signedRequest A SignedRequest object returned by a stamping method.
711
+ * @returns The parsed JSON response from ZeroXKey.
712
+ * @throws ZeroXKeyNetworkError if the request fails.
713
+ */
714
+ // TODO: (breaking change) remove this function
715
+ async function sendSignedRequest(signedRequest) {
716
+ const headers = {
717
+ "Content-Type": "application/json",
718
+ "X-Client-Version": VERSION,
719
+ [signedRequest.stamp.stampHeaderName]: signedRequest.stamp.stampHeaderValue,
720
+ };
721
+ const res = await fetch(signedRequest.url, {
722
+ method: "POST",
723
+ headers,
724
+ body: signedRequest.body,
725
+ });
726
+ if (!res.ok) {
727
+ const errorText = await res.text();
728
+ throw new ZeroXKeyNetworkError("Signed request failed", res.status, ZeroXKeyErrorCodes.BAD_RESPONSE, errorText);
729
+ }
730
+ return res.json();
731
+ }
732
+ /**
733
+ * @internal
734
+ * Executes an async function with error handling.
735
+ *
736
+ * @param fn The async function to execute with error handling
737
+ * @param errorOptions Options for customizing error handling
738
+ * @param errorOptions.catchFn Optional function to execute in the catch block
739
+ * @param errorOptions.errorMessage The default error message to use if no custom message is found
740
+ * @param errorOptions.errorCode The default error code to use if no custom message is found
741
+ * @param errorOptions.customErrorsByCodes Optional mapping of error codes to custom messages, if you're trying to target a specific error code and surface a custom message, use this
742
+ * @param errorOptions.customErrorsByMessages Optional mapping of error messages to custom messages, if you're trying to target a specific error message and surface a custom message, use this
743
+ * @param finallyFn Optional function to execute in the finally block
744
+ * @returns The result of the async function or throws an error
745
+ */
746
+ async function withZeroXKeyErrorHandling(fn, catchOptions, finallyOptions) {
747
+ const { errorMessage, errorCode, customErrorsByCodes, catchFn } = catchOptions;
748
+ // Merge global error mappings with any caller-provided ones.
749
+ // - Start with the globals so they’re always available.
750
+ // - Spread the caller’s entries last so they override globals on conflicts.
751
+ // - If the caller didn’t provide any, just fall back to the globals.
752
+ const customErrorsByMessages = catchOptions.customErrorsByMessages
753
+ ? { ...globalErrorsToMatch, ...catchOptions.customErrorsByMessages }
754
+ : globalErrorsToMatch;
755
+ const finallyFn = finallyOptions?.finallyFn;
756
+ try {
757
+ return await fn();
758
+ }
759
+ catch (error) {
760
+ await catchFn?.();
761
+ // some things throw plain objects (not Error instances), which would stringify as `[object Object]`
762
+ // we normalize here to always produce a readable error message before wrapping it in ZeroXKeyError.
763
+ const normalizedMessage = error instanceof Error && typeof error.message === "string"
764
+ ? error.message
765
+ : typeof error?.message === "string"
766
+ ? error.message
767
+ : JSON.stringify(error);
768
+ if (error instanceof ZeroXKeyError) {
769
+ const customCodeMessage = customErrorsByCodes?.[error.code];
770
+ if (customCodeMessage) {
771
+ throw new ZeroXKeyError(customCodeMessage.message, customCodeMessage.code, error);
772
+ }
773
+ throwMatchingMessage(error.message, customErrorsByMessages, error);
774
+ throw error;
775
+ }
776
+ else if (error instanceof ZeroXKeyRequestError) {
777
+ throwMatchingMessage(normalizedMessage, customErrorsByMessages, error);
778
+ throw new ZeroXKeyError(errorMessage, errorCode, error);
779
+ }
780
+ else if (error instanceof Error) {
781
+ throwMatchingMessage(normalizedMessage, customErrorsByMessages, error);
782
+ // Wrap other errors in a ZeroXKeyError
783
+ throw new ZeroXKeyError(errorMessage, errorCode, error);
784
+ }
785
+ else {
786
+ throwMatchingMessage(normalizedMessage, customErrorsByMessages, error);
787
+ // Handle non-Error exceptions
788
+ throw new ZeroXKeyError(normalizedMessage, errorCode, error);
789
+ }
790
+ }
791
+ finally {
792
+ await finallyFn?.();
793
+ }
794
+ }
795
+ /**
796
+ * Throws a ZeroXKeyError with a custom message if the error message matches any key in customMessageByMessages.
797
+ * If no match is found, it does nothing.
798
+ *
799
+ * @param errorMessage The error message to check against the custom messages.
800
+ * @param customErrorsByMessages An object mapping error messages to custom messages and codes.
801
+ * @param error The original error that triggered this function.
802
+ */
803
+ const throwMatchingMessage = (errorMessage, customErrorsByMessages, error) => {
804
+ if (customErrorsByMessages &&
805
+ Object.keys(customErrorsByMessages).length > 0) {
806
+ Object.keys(customErrorsByMessages).forEach((key) => {
807
+ if (errorMessage.includes(key)) {
808
+ throw new ZeroXKeyError(customErrorsByMessages[key].message, customErrorsByMessages[key].code, error);
809
+ }
810
+ });
811
+ }
812
+ };
813
+ /**
814
+ * @internal
815
+ *
816
+ * Asserts that the provided key pair is a valid P-256 ECDSA key pair.
817
+ * @param pair The key pair to validate.
818
+ */
819
+ async function assertValidP256ECDSAKeyPair(pair) {
820
+ const { privateKey, publicKey } = pair;
821
+ // Check basic shape
822
+ if (!(privateKey instanceof CryptoKey) || !(publicKey instanceof CryptoKey)) {
823
+ throw new ZeroXKeyError("Both keys must be CryptoKey instances.", ZeroXKeyErrorCodes.INVALID_REQUEST);
824
+ }
825
+ if (privateKey.type !== "private")
826
+ throw new ZeroXKeyError("privateKey.type must be 'private'.", ZeroXKeyErrorCodes.INVALID_REQUEST);
827
+ if (publicKey.type !== "public")
828
+ throw new ZeroXKeyError("publicKey.type must be 'public'.", ZeroXKeyErrorCodes.INVALID_REQUEST);
829
+ // Verify extractability and usages
830
+ if (privateKey.extractable !== false) {
831
+ throw new ZeroXKeyError("Provided privateKey must be non-extractable.", ZeroXKeyErrorCodes.INVALID_REQUEST);
832
+ }
833
+ if (!privateKey.usages.includes("sign")) {
834
+ throw new ZeroXKeyError("privateKey must have 'sign' in keyUsages.", ZeroXKeyErrorCodes.INVALID_REQUEST);
835
+ }
836
+ if (!publicKey.usages.includes("verify")) {
837
+ throw new ZeroXKeyError("publicKey must have 'verify' in keyUsages.", ZeroXKeyErrorCodes.INVALID_REQUEST);
838
+ }
839
+ // Algorithm checks (must be ECDSA on P-256)
840
+ const pAlg = privateKey.algorithm;
841
+ const pubAlg = publicKey.algorithm;
842
+ if (pAlg.name !== "ECDSA" || pubAlg.name !== "ECDSA") {
843
+ throw new ZeroXKeyError("Keys must be ECDSA keys.", ZeroXKeyErrorCodes.INVALID_REQUEST);
844
+ }
845
+ if (pAlg.namedCurve !== "P-256" || pubAlg.namedCurve !== "P-256") {
846
+ throw new ZeroXKeyError("Keys must be on the P-256 curve.", ZeroXKeyErrorCodes.INVALID_REQUEST);
847
+ }
848
+ // Public key export sanity (should be uncompressed 65 bytes starting with 0x04)
849
+ const rawPub = new Uint8Array(await crypto.subtle.exportKey("raw", publicKey));
850
+ if (rawPub.length !== 65 || rawPub[0] !== 0x04) {
851
+ throw new ZeroXKeyError("Public key must be an uncompressed P-256 point (65 bytes, leading 0x04).", ZeroXKeyErrorCodes.INVALID_REQUEST);
852
+ }
853
+ // Prove the pair matches: sign→verify a test message
854
+ const msg = crypto.getRandomValues(new Uint8Array(32));
855
+ const sig = await crypto.subtle.sign({ name: "ECDSA", hash: "SHA-256" }, privateKey, msg);
856
+ const ok = await crypto.subtle.verify({ name: "ECDSA", hash: "SHA-256" }, publicKey, sig, msg);
857
+ if (!ok) {
858
+ throw new ZeroXKeyError("publicKey does not match privateKey (verify failed).", ZeroXKeyErrorCodes.INVALID_REQUEST);
859
+ }
860
+ }
861
+ function isValidPasskeyName(name) {
862
+ const nameRegex = isReactNative()
863
+ ? /^[a-zA-Z0-9 _\-:\/\.]{1,64}$/
864
+ : /^[a-zA-Z0-9 _\-:\/\.]+$/;
865
+ if (!nameRegex.test(name)) {
866
+ throw new ZeroXKeyError("Passkey name must be 1-64 characters and only contain letters, numbers, spaces, dashes, underscores, colons, or slashes.", ZeroXKeyErrorCodes.INVALID_REQUEST);
867
+ }
868
+ return name;
869
+ }
870
+ function mapAccountsToWallet(accounts, walletMap) {
871
+ // map of walletId to Wallet
872
+ // map all wallet accounts to their wallets
873
+ accounts.forEach(async (account) => {
874
+ if (walletMap.has(account.walletDetails.walletId)) {
875
+ const wallet = walletMap.get(account.walletDetails.walletId);
876
+ wallet.accounts.push({
877
+ ...account,
878
+ source: WalletSource.Embedded,
879
+ });
880
+ return;
881
+ }
882
+ else {
883
+ walletMap.set(account.walletDetails.walletId, {
884
+ source: WalletSource.Embedded,
885
+ walletId: account.walletDetails.walletId,
886
+ walletName: account.walletDetails.walletName,
887
+ createdAt: account.walletDetails.createdAt,
888
+ updatedAt: account.walletDetails.updatedAt,
889
+ exported: account.walletDetails.exported,
890
+ imported: account.walletDetails.imported,
891
+ accounts: [
892
+ {
893
+ ...account,
894
+ source: WalletSource.Embedded,
895
+ },
896
+ ],
897
+ });
898
+ }
899
+ });
900
+ return Array.from(walletMap.values());
901
+ }
902
+ async function withTimeout(promise, ms, label) {
903
+ let timeout;
904
+ const timer = new Promise((_, reject) => {
905
+ timeout = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
906
+ });
907
+ return Promise.race([promise, timer]).finally(() => clearTimeout(timeout));
908
+ }
909
+ async function fetchAllWalletAccountsWithCursor(httpClient, organizationId, stampWith) {
910
+ let hasMore = true;
911
+ let cursor;
912
+ const accounts = [];
913
+ const limit = 100;
914
+ while (hasMore) {
915
+ const response = await httpClient.getWalletAccounts({
916
+ organizationId,
917
+ includeWalletDetails: true,
918
+ paginationOptions: {
919
+ limit: limit.toString(),
920
+ ...(cursor && { after: cursor }),
921
+ },
922
+ }, stampWith);
923
+ if (!response || !response.accounts) {
924
+ throw new ZeroXKeyError("No wallet accounts found in the response", ZeroXKeyErrorCodes.BAD_RESPONSE);
925
+ }
926
+ accounts.push(...response.accounts);
927
+ hasMore = response.accounts.length === limit;
928
+ cursor =
929
+ response.accounts && response.accounts.length > 0
930
+ ? response.accounts[response.accounts.length - 1]?.walletAccountId
931
+ : undefined;
932
+ }
933
+ return accounts;
934
+ }
935
+ function decodeVerificationToken(verificationToken) {
936
+ const [, payloadB64] = verificationToken.split(".");
937
+ if (!payloadB64) {
938
+ throw new Error("Invalid token: missing payload");
939
+ }
940
+ const json = atob(payloadB64);
941
+ return JSON.parse(json);
942
+ }
943
+ function getClientSignatureMessageForLogin({ verificationToken, sessionPublicKey = undefined, }) {
944
+ try {
945
+ const decoded = decodeVerificationToken(verificationToken);
946
+ if (!decoded.public_key)
947
+ throw new ZeroXKeyError("Invalid verification token: missing publicKey", ZeroXKeyErrorCodes.INVALID_REQUEST);
948
+ const verificationPublicKey = decoded.public_key;
949
+ // if a session public key is provided, we use it instead
950
+ const resolvedSessionPublicKey = sessionPublicKey || verificationPublicKey;
951
+ const usage = { publicKey: resolvedSessionPublicKey };
952
+ const payload = {
953
+ login: usage,
954
+ tokenId: decoded.id,
955
+ type: "USAGE_TYPE_LOGIN",
956
+ };
957
+ const json = JSON.stringify(payload);
958
+ return { message: json, publicKey: verificationPublicKey };
959
+ }
960
+ catch (error) {
961
+ throw new ZeroXKeyError("Failed to create client signature bundle for login", ZeroXKeyErrorCodes.UNKNOWN, error);
962
+ }
963
+ }
964
+ function getClientSignatureMessageForSignup({ verificationToken, email, phoneNumber, apiKeys, authenticators, oauthProviders, }) {
965
+ try {
966
+ const decoded = decodeVerificationToken(verificationToken);
967
+ if (!decoded.public_key)
968
+ throw new ZeroXKeyError("Invalid verification token: missing publicKey", ZeroXKeyErrorCodes.INVALID_REQUEST);
969
+ const verificationPublicKey = decoded.public_key;
970
+ const usage = {
971
+ ...(apiKeys ? { apiKeys } : {}),
972
+ ...(authenticators ? { authenticators } : {}),
973
+ ...(oauthProviders ? { oauthProviders } : {}),
974
+ ...(email ? { email } : {}),
975
+ ...(phoneNumber ? { phoneNumber } : {}),
976
+ };
977
+ const payload = {
978
+ signup: usage,
979
+ tokenId: decoded.id,
980
+ type: "USAGE_TYPE_SIGNUP",
981
+ };
982
+ const json = JSON.stringify(payload);
983
+ return { message: json, publicKey: verificationPublicKey };
984
+ }
985
+ catch (error) {
986
+ throw new ZeroXKeyError("Failed to create client signature bundle for signup", ZeroXKeyErrorCodes.UNKNOWN, error);
987
+ }
988
+ }
989
+ /**
990
+ * Wraps a promise with a timeout. If the promise doesn't resolve within
991
+ * the specified duration, it resolves to the fallback value instead of throwing.
992
+ *
993
+ * @param promise - The promise to wrap.
994
+ * @param fallback - Value to return if the timeout is reached.
995
+ * @param timeoutMs - Timeout duration in milliseconds. Defaults to 1000ms.
996
+ * @returns The result of the promise, or the fallback if timed out.
997
+ */
998
+ const withTimeoutFallback = (promise, fallback, timeoutMs) => {
999
+ const timeout = 1000;
1000
+ return Promise.race([
1001
+ promise,
1002
+ new Promise((resolve) => setTimeout(() => resolve(fallback), timeout)),
1003
+ ]);
1004
+ };
1005
+
1006
+ export { addressFormatConfig, addressFromPublicKey, assertValidP256ECDSAKeyPair, broadcastTransaction, buildSignUpBody, createWalletAccountFromAddressFormat, decodeVerificationToken, fetchAllWalletAccountsWithCursor, findWalletProviderFromAddress, generateRandomBuffer, generateWalletAccountsFromAddressFormat, getActiveSessionOrThrowIfRequired, getAuthProxyConfig, getAuthenticatorAddresses, getClientSignatureMessageForLogin, getClientSignatureMessageForSignup, getCurveTypeFromProvider, getEncodedMessage, getEncodingType, getHashFunction, getPolicySignature, getPublicKeyFromStampHeader, getSignatureSchemeFromProvider, googleISS, hexSignedTxToBase58, isEthereumProvider, isReactNative, isSolanaProvider, isValidPasskeyName, isWalletAccountArray, isWeb, mapAccountsToWallet, parseSession, sendSignedRequest, splitSignature, toExternalTimestamp, withTimeout, withTimeoutFallback, withZeroXKeyErrorHandling };
1007
+ //# sourceMappingURL=utils.mjs.map