@sip-protocol/sdk 0.3.2 → 0.4.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 (47) hide show
  1. package/dist/browser.d.mts +2 -2
  2. package/dist/browser.d.ts +2 -2
  3. package/dist/browser.js +1019 -146
  4. package/dist/browser.mjs +49 -1
  5. package/dist/chunk-AOZIY3GU.mjs +12995 -0
  6. package/dist/chunk-BCLIX5T2.mjs +12940 -0
  7. package/dist/chunk-FKXPHKYD.mjs +12955 -0
  8. package/dist/chunk-OPQ2GQIO.mjs +13013 -0
  9. package/dist/index-BcWNakUD.d.ts +7990 -0
  10. package/dist/index-BsKY3Hr0.d.mts +7990 -0
  11. package/dist/index.d.mts +2 -2
  12. package/dist/index.d.ts +2 -2
  13. package/dist/index.js +990 -117
  14. package/dist/index.mjs +49 -1
  15. package/package.json +2 -1
  16. package/src/adapters/near-intents.ts +8 -0
  17. package/src/bitcoin/index.ts +51 -0
  18. package/src/bitcoin/silent-payments.ts +865 -0
  19. package/src/bitcoin/taproot.ts +590 -0
  20. package/src/cosmos/ibc-stealth.ts +825 -0
  21. package/src/cosmos/index.ts +83 -0
  22. package/src/cosmos/stealth.ts +487 -0
  23. package/src/index.ts +51 -0
  24. package/src/move/aptos.ts +369 -0
  25. package/src/move/index.ts +35 -0
  26. package/src/move/sui.ts +367 -0
  27. package/src/oracle/types.ts +8 -0
  28. package/src/settlement/backends/direct-chain.ts +8 -0
  29. package/src/stealth.ts +3 -3
  30. package/src/validation.ts +42 -1
  31. package/src/wallet/aptos/adapter.ts +422 -0
  32. package/src/wallet/aptos/index.ts +10 -0
  33. package/src/wallet/aptos/mock.ts +410 -0
  34. package/src/wallet/aptos/types.ts +278 -0
  35. package/src/wallet/bitcoin/adapter.ts +470 -0
  36. package/src/wallet/bitcoin/index.ts +38 -0
  37. package/src/wallet/bitcoin/mock.ts +516 -0
  38. package/src/wallet/bitcoin/types.ts +274 -0
  39. package/src/wallet/cosmos/adapter.ts +484 -0
  40. package/src/wallet/cosmos/index.ts +63 -0
  41. package/src/wallet/cosmos/mock.ts +596 -0
  42. package/src/wallet/cosmos/types.ts +462 -0
  43. package/src/wallet/index.ts +127 -0
  44. package/src/wallet/sui/adapter.ts +471 -0
  45. package/src/wallet/sui/index.ts +10 -0
  46. package/src/wallet/sui/mock.ts +439 -0
  47. package/src/wallet/sui/types.ts +245 -0
@@ -0,0 +1,484 @@
1
+ /**
2
+ * Cosmos Wallet Adapter
3
+ *
4
+ * Implementation of WalletAdapter for Cosmos ecosystem.
5
+ * Supports Keplr, Leap, Cosmostation, and other Cosmos wallets.
6
+ */
7
+
8
+ import type {
9
+ HexString,
10
+ Asset,
11
+ Signature,
12
+ UnsignedTransaction,
13
+ SignedTransaction,
14
+ TransactionReceipt,
15
+ } from '@sip-protocol/types'
16
+ import { WalletErrorCode } from '@sip-protocol/types'
17
+ import { BaseWalletAdapter } from '../base-adapter'
18
+ import { WalletError } from '../errors'
19
+ import type {
20
+ Keplr,
21
+ CosmosAdapterConfig,
22
+ CosmosWalletName,
23
+ Key,
24
+ StdSignDoc,
25
+ DirectSignDoc,
26
+ AminoSignResponse,
27
+ DirectSignResponse,
28
+ CosmosUnsignedTransaction,
29
+ } from './types'
30
+ import {
31
+ getCosmosProvider,
32
+ cosmosPublicKeyToHex,
33
+ getDefaultRpcEndpoint,
34
+ getDefaultRestEndpoint,
35
+ CosmosChainId,
36
+ } from './types'
37
+
38
+ /**
39
+ * Cosmos wallet adapter implementation
40
+ *
41
+ * Provides SIP-compatible wallet interface for Cosmos ecosystem.
42
+ * Works with Keplr, Leap, Cosmostation, and other Cosmos wallets.
43
+ *
44
+ * @example Browser usage with Keplr
45
+ * ```typescript
46
+ * const wallet = new CosmosWalletAdapter({
47
+ * wallet: 'keplr',
48
+ * chainId: 'cosmoshub-4',
49
+ * })
50
+ * await wallet.connect()
51
+ *
52
+ * const balance = await wallet.getBalance()
53
+ * console.log(`Balance: ${balance} uatom`)
54
+ *
55
+ * // Sign a message
56
+ * const sig = await wallet.signMessage(new TextEncoder().encode('Hello'))
57
+ * ```
58
+ *
59
+ * @example With custom RPC endpoint
60
+ * ```typescript
61
+ * const wallet = new CosmosWalletAdapter({
62
+ * wallet: 'keplr',
63
+ * chainId: 'osmosis-1',
64
+ * rpcEndpoint: 'https://my-rpc.example.com',
65
+ * })
66
+ * ```
67
+ */
68
+ export class CosmosWalletAdapter extends BaseWalletAdapter {
69
+ readonly chain = 'cosmos' as const
70
+ readonly name: string
71
+
72
+ private provider: Keplr | undefined
73
+ private walletName: CosmosWalletName
74
+ private _chainId: string
75
+ private rpcEndpoint: string
76
+ private restEndpoint: string
77
+ private bech32Prefix: string
78
+ private keyInfo: Key | undefined
79
+
80
+ constructor(config: CosmosAdapterConfig = {}) {
81
+ super()
82
+ this.walletName = config.wallet ?? 'keplr'
83
+ this.name = `cosmos-${this.walletName}`
84
+ this._chainId = config.chainId ?? CosmosChainId.COSMOSHUB
85
+ this.rpcEndpoint = config.rpcEndpoint ?? getDefaultRpcEndpoint(this._chainId)
86
+ this.restEndpoint = config.restEndpoint ?? getDefaultRestEndpoint(this._chainId)
87
+ this.bech32Prefix = config.bech32Prefix ?? 'cosmos'
88
+
89
+ // Allow injecting provider for testing
90
+ if (config.provider) {
91
+ this.provider = config.provider
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Get the current Cosmos chain ID
97
+ */
98
+ getChainId(): string {
99
+ return this._chainId
100
+ }
101
+
102
+ /**
103
+ * Get the RPC endpoint
104
+ */
105
+ getRpcEndpoint(): string {
106
+ return this.rpcEndpoint
107
+ }
108
+
109
+ /**
110
+ * Get the REST endpoint
111
+ */
112
+ getRestEndpoint(): string {
113
+ return this.restEndpoint
114
+ }
115
+
116
+ /**
117
+ * Set the RPC endpoint
118
+ */
119
+ setRpcEndpoint(endpoint: string): void {
120
+ this.rpcEndpoint = endpoint
121
+ }
122
+
123
+ /**
124
+ * Set the REST endpoint
125
+ */
126
+ setRestEndpoint(endpoint: string): void {
127
+ this.restEndpoint = endpoint
128
+ }
129
+
130
+ /**
131
+ * Get the Bech32 address prefix
132
+ */
133
+ getBech32Prefix(): string {
134
+ return this.bech32Prefix
135
+ }
136
+
137
+ /**
138
+ * Connect to the wallet
139
+ */
140
+ async connect(): Promise<void> {
141
+ this._connectionState = 'connecting'
142
+
143
+ try {
144
+ // Get provider if not already set
145
+ if (!this.provider) {
146
+ this.provider = getCosmosProvider(this.walletName)
147
+ }
148
+
149
+ if (!this.provider) {
150
+ this.setError(
151
+ WalletErrorCode.NOT_INSTALLED,
152
+ `${this.walletName} wallet is not installed`
153
+ )
154
+ throw new WalletError(
155
+ `${this.walletName} wallet is not installed`,
156
+ WalletErrorCode.NOT_INSTALLED
157
+ )
158
+ }
159
+
160
+ // Enable the chain
161
+ await this.provider.enable(this._chainId)
162
+
163
+ // Get key info
164
+ this.keyInfo = await this.provider.getKey(this._chainId)
165
+
166
+ if (!this.keyInfo) {
167
+ throw new WalletError(
168
+ 'No key returned from wallet',
169
+ WalletErrorCode.CONNECTION_FAILED
170
+ )
171
+ }
172
+
173
+ // Update state
174
+ const address = this.keyInfo.address
175
+ const hexPubKey = cosmosPublicKeyToHex(this.keyInfo.pubKey)
176
+ this.setConnected(address, hexPubKey)
177
+ } catch (error) {
178
+ const message = error instanceof Error ? error.message : 'Connection failed'
179
+
180
+ // Check if user rejected
181
+ if (message.includes('Request rejected') || message.includes('rejected')) {
182
+ this.setError(WalletErrorCode.CONNECTION_REJECTED, message)
183
+ throw new WalletError(message, WalletErrorCode.CONNECTION_REJECTED)
184
+ }
185
+
186
+ this.setError(WalletErrorCode.CONNECTION_FAILED, message)
187
+ throw error instanceof WalletError
188
+ ? error
189
+ : new WalletError(message, WalletErrorCode.CONNECTION_FAILED, { cause: error as Error })
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Disconnect from the wallet
195
+ */
196
+ async disconnect(): Promise<void> {
197
+ this.setDisconnected('User disconnected')
198
+ this.provider = undefined
199
+ this.keyInfo = undefined
200
+ }
201
+
202
+ /**
203
+ * Sign a message using signArbitrary
204
+ */
205
+ async signMessage(message: Uint8Array): Promise<Signature> {
206
+ this.requireConnected()
207
+
208
+ if (!this.provider) {
209
+ throw new WalletError('Provider not available', WalletErrorCode.NOT_CONNECTED)
210
+ }
211
+
212
+ try {
213
+ const stdSig = await this.provider.signArbitrary(
214
+ this._chainId,
215
+ this._address,
216
+ message
217
+ )
218
+
219
+ return {
220
+ signature: ('0x' + Buffer.from(stdSig.signature, 'base64').toString('hex')) as HexString,
221
+ publicKey: this._publicKey as HexString,
222
+ }
223
+ } catch (error) {
224
+ const message = error instanceof Error ? error.message : 'Signing failed'
225
+
226
+ if (message.includes('Request rejected') || message.includes('rejected')) {
227
+ throw new WalletError(message, WalletErrorCode.SIGNING_REJECTED)
228
+ }
229
+
230
+ throw new WalletError(message, WalletErrorCode.SIGNING_FAILED, {
231
+ cause: error as Error,
232
+ })
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Sign a transaction
238
+ *
239
+ * The transaction data should contain either aminoSignDoc or directSignDoc
240
+ */
241
+ async signTransaction(tx: UnsignedTransaction): Promise<SignedTransaction> {
242
+ this.requireConnected()
243
+
244
+ if (!this.provider) {
245
+ throw new WalletError('Provider not available', WalletErrorCode.NOT_CONNECTED)
246
+ }
247
+
248
+ try {
249
+ const cosmosTx = tx.data as CosmosUnsignedTransaction
250
+
251
+ let signature: Signature
252
+ let signResponse: AminoSignResponse | DirectSignResponse
253
+
254
+ // Use direct signing if directSignDoc is provided, otherwise use amino
255
+ if (cosmosTx.directSignDoc) {
256
+ signResponse = await this.provider.signDirect(
257
+ this._chainId,
258
+ this._address,
259
+ {
260
+ bodyBytes: cosmosTx.directSignDoc.bodyBytes,
261
+ authInfoBytes: cosmosTx.directSignDoc.authInfoBytes,
262
+ chainId: cosmosTx.directSignDoc.chainId,
263
+ accountNumber: cosmosTx.directSignDoc.accountNumber,
264
+ }
265
+ )
266
+
267
+ const directResponse = signResponse as DirectSignResponse
268
+ signature = {
269
+ signature: ('0x' + Buffer.from(directResponse.signature.signature, 'base64').toString('hex')) as HexString,
270
+ publicKey: this._publicKey as HexString,
271
+ }
272
+ } else if (cosmosTx.aminoSignDoc) {
273
+ signResponse = await this.provider.signAmino(
274
+ this._chainId,
275
+ this._address,
276
+ cosmosTx.aminoSignDoc
277
+ )
278
+
279
+ const aminoResponse = signResponse as AminoSignResponse
280
+ signature = {
281
+ signature: ('0x' + Buffer.from(aminoResponse.signature.signature, 'base64').toString('hex')) as HexString,
282
+ publicKey: this._publicKey as HexString,
283
+ }
284
+ } else {
285
+ throw new WalletError(
286
+ 'Transaction must contain either aminoSignDoc or directSignDoc',
287
+ WalletErrorCode.INVALID_TRANSACTION
288
+ )
289
+ }
290
+
291
+ // Serialize response, handling BigInt
292
+ const responseStr = JSON.stringify(signResponse, (_, value) =>
293
+ typeof value === 'bigint' ? value.toString() : value
294
+ )
295
+
296
+ return {
297
+ unsigned: tx,
298
+ signatures: [signature],
299
+ serialized: ('0x' + Buffer.from(responseStr).toString('hex')) as HexString,
300
+ }
301
+ } catch (error) {
302
+ const message = error instanceof Error ? error.message : 'Signing failed'
303
+
304
+ if (message.includes('Request rejected') || message.includes('rejected')) {
305
+ throw new WalletError(message, WalletErrorCode.SIGNING_REJECTED)
306
+ }
307
+
308
+ throw new WalletError(message, WalletErrorCode.SIGNING_FAILED, {
309
+ cause: error as Error,
310
+ })
311
+ }
312
+ }
313
+
314
+ /**
315
+ * Sign and send a transaction
316
+ *
317
+ * Note: Cosmos wallets don't typically provide a signAndSend method,
318
+ * so this will sign the transaction but you'll need to broadcast it separately
319
+ */
320
+ async signAndSendTransaction(tx: UnsignedTransaction): Promise<TransactionReceipt> {
321
+ this.requireConnected()
322
+
323
+ try {
324
+ // Sign the transaction
325
+ const signed = await this.signTransaction(tx)
326
+
327
+ // For Cosmos, we would need to broadcast via RPC
328
+ // This is a simplified implementation
329
+ const mockTxHash = ('0x' + Buffer.from(`cosmos_tx_${Date.now()}`).toString('hex')) as HexString
330
+
331
+ return {
332
+ txHash: mockTxHash,
333
+ status: 'pending', // Transaction is signed but not broadcast
334
+ timestamp: Date.now(),
335
+ }
336
+ } catch (error) {
337
+ const message = error instanceof Error ? error.message : 'Transaction failed'
338
+
339
+ if (message.includes('Request rejected') || message.includes('rejected')) {
340
+ throw new WalletError(message, WalletErrorCode.TRANSACTION_REJECTED)
341
+ }
342
+
343
+ if (message.includes('insufficient') || message.includes('Insufficient')) {
344
+ throw new WalletError(message, WalletErrorCode.INSUFFICIENT_FUNDS)
345
+ }
346
+
347
+ throw new WalletError(message, WalletErrorCode.TRANSACTION_FAILED, {
348
+ cause: error as Error,
349
+ })
350
+ }
351
+ }
352
+
353
+ /**
354
+ * Get native token balance (e.g., ATOM, OSMO)
355
+ */
356
+ async getBalance(): Promise<bigint> {
357
+ this.requireConnected()
358
+
359
+ try {
360
+ const response = await fetch(`${this.restEndpoint}/cosmos/bank/v1beta1/balances/${this._address}`)
361
+
362
+ if (!response.ok) {
363
+ throw new Error(`Failed to fetch balance: ${response.statusText}`)
364
+ }
365
+
366
+ const data = await response.json()
367
+ const balances = data.balances as Array<{ denom: string; amount: string }>
368
+
369
+ // Get the first balance or 0
370
+ const balance = balances[0]?.amount ?? '0'
371
+ return BigInt(balance)
372
+ } catch (error) {
373
+ throw new WalletError(
374
+ 'Failed to get balance',
375
+ WalletErrorCode.UNKNOWN,
376
+ { cause: error as Error }
377
+ )
378
+ }
379
+ }
380
+
381
+ /**
382
+ * Get token balance by denomination
383
+ */
384
+ async getTokenBalance(asset: Asset): Promise<bigint> {
385
+ this.requireConnected()
386
+
387
+ if (asset.chain !== 'cosmos') {
388
+ throw new WalletError(
389
+ `Asset chain ${asset.chain} not supported by Cosmos adapter`,
390
+ WalletErrorCode.UNSUPPORTED_CHAIN
391
+ )
392
+ }
393
+
394
+ try {
395
+ const response = await fetch(`${this.restEndpoint}/cosmos/bank/v1beta1/balances/${this._address}`)
396
+
397
+ if (!response.ok) {
398
+ throw new Error(`Failed to fetch balance: ${response.statusText}`)
399
+ }
400
+
401
+ const data = await response.json()
402
+ const balances = data.balances as Array<{ denom: string; amount: string }>
403
+
404
+ // Find the balance for the specified denomination
405
+ const denom = asset.address ?? asset.symbol.toLowerCase()
406
+ const balance = balances.find((b) => b.denom === denom)?.amount ?? '0'
407
+
408
+ return BigInt(balance)
409
+ } catch (error) {
410
+ throw new WalletError(
411
+ 'Failed to get token balance',
412
+ WalletErrorCode.UNKNOWN,
413
+ { cause: error as Error }
414
+ )
415
+ }
416
+ }
417
+
418
+ /**
419
+ * Sign using Amino (legacy method)
420
+ */
421
+ async signAmino(
422
+ signerAddress: string,
423
+ signDoc: StdSignDoc
424
+ ): Promise<AminoSignResponse> {
425
+ this.requireConnected()
426
+
427
+ if (!this.provider) {
428
+ throw new WalletError('Provider not available', WalletErrorCode.NOT_CONNECTED)
429
+ }
430
+
431
+ try {
432
+ return await this.provider.signAmino(this._chainId, signerAddress, signDoc)
433
+ } catch (error) {
434
+ const message = error instanceof Error ? error.message : 'Signing failed'
435
+ throw new WalletError(message, WalletErrorCode.SIGNING_FAILED, {
436
+ cause: error as Error,
437
+ })
438
+ }
439
+ }
440
+
441
+ /**
442
+ * Sign using Direct (protobuf method)
443
+ */
444
+ async signDirect(
445
+ signerAddress: string,
446
+ signDoc: DirectSignDoc
447
+ ): Promise<DirectSignResponse> {
448
+ this.requireConnected()
449
+
450
+ if (!this.provider) {
451
+ throw new WalletError('Provider not available', WalletErrorCode.NOT_CONNECTED)
452
+ }
453
+
454
+ try {
455
+ return await this.provider.signDirect(this._chainId, signerAddress, {
456
+ bodyBytes: signDoc.bodyBytes,
457
+ authInfoBytes: signDoc.authInfoBytes,
458
+ chainId: signDoc.chainId,
459
+ accountNumber: signDoc.accountNumber,
460
+ })
461
+ } catch (error) {
462
+ const message = error instanceof Error ? error.message : 'Signing failed'
463
+ throw new WalletError(message, WalletErrorCode.SIGNING_FAILED, {
464
+ cause: error as Error,
465
+ })
466
+ }
467
+ }
468
+
469
+ /**
470
+ * Get account info
471
+ */
472
+ getKeyInfo(): Key | undefined {
473
+ return this.keyInfo
474
+ }
475
+ }
476
+
477
+ /**
478
+ * Create a Cosmos wallet adapter with default configuration
479
+ */
480
+ export function createCosmosAdapter(
481
+ config: CosmosAdapterConfig = {}
482
+ ): CosmosWalletAdapter {
483
+ return new CosmosWalletAdapter(config)
484
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Cosmos Wallet Module
3
+ *
4
+ * Exports for Cosmos ecosystem wallet adapters (Keplr, Leap, etc.)
5
+ */
6
+
7
+ // Adapter
8
+ export { CosmosWalletAdapter, createCosmosAdapter } from './adapter'
9
+
10
+ // Mock adapter
11
+ export {
12
+ MockCosmosAdapter,
13
+ createMockCosmosAdapter,
14
+ createMockCosmosProvider,
15
+ type MockCosmosAdapterConfig,
16
+ } from './mock'
17
+
18
+ // Types
19
+ export type {
20
+ // Account & Key types
21
+ CosmosAccountData,
22
+ CosmosAlgo,
23
+ Key,
24
+ PubKey,
25
+
26
+ // Signing types
27
+ StdSignDoc,
28
+ StdFee,
29
+ Coin,
30
+ CosmosMsg,
31
+ AminoSignResponse,
32
+ StdSignature,
33
+ DirectSignDoc,
34
+ DirectSignResponse,
35
+
36
+ // Wallet types
37
+ Keplr,
38
+ KeplrSignOptions,
39
+ OfflineSigner,
40
+ OfflineAminoSigner,
41
+
42
+ // Chain types
43
+ ChainInfo,
44
+ Currency,
45
+ CosmosWalletName,
46
+ CosmosChainIdType,
47
+
48
+ // Configuration
49
+ CosmosAdapterConfig,
50
+ CosmosUnsignedTransaction,
51
+ CosmosSignature,
52
+ } from './types'
53
+
54
+ // Utilities
55
+ export {
56
+ getCosmosProvider,
57
+ detectCosmosWallets,
58
+ cosmosPublicKeyToHex,
59
+ bech32ToHex,
60
+ getDefaultRpcEndpoint,
61
+ getDefaultRestEndpoint,
62
+ CosmosChainId,
63
+ } from './types'