@sip-protocol/sdk 0.3.1 → 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.
- package/dist/browser.d.mts +2 -2
- package/dist/browser.d.ts +2 -2
- package/dist/browser.js +1028 -146
- package/dist/browser.mjs +49 -1
- package/dist/chunk-AOZIY3GU.mjs +12995 -0
- package/dist/chunk-BCLIX5T2.mjs +12940 -0
- package/dist/chunk-EU4UEWWG.mjs +12164 -0
- package/dist/chunk-FKXPHKYD.mjs +12955 -0
- package/dist/chunk-OPQ2GQIO.mjs +13013 -0
- package/dist/index-BcWNakUD.d.ts +7990 -0
- package/dist/index-BsKY3Hr0.d.mts +7990 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +999 -117
- package/dist/index.mjs +49 -1
- package/package.json +2 -1
- package/src/adapters/near-intents.ts +8 -0
- package/src/bitcoin/index.ts +51 -0
- package/src/bitcoin/silent-payments.ts +865 -0
- package/src/bitcoin/taproot.ts +590 -0
- package/src/cosmos/ibc-stealth.ts +825 -0
- package/src/cosmos/index.ts +83 -0
- package/src/cosmos/stealth.ts +487 -0
- package/src/index.ts +51 -0
- package/src/move/aptos.ts +369 -0
- package/src/move/index.ts +35 -0
- package/src/move/sui.ts +367 -0
- package/src/oracle/types.ts +8 -0
- package/src/settlement/backends/direct-chain.ts +8 -0
- package/src/settlement/backends/near-intents.ts +11 -0
- package/src/stealth.ts +3 -3
- package/src/validation.ts +42 -1
- package/src/wallet/aptos/adapter.ts +422 -0
- package/src/wallet/aptos/index.ts +10 -0
- package/src/wallet/aptos/mock.ts +410 -0
- package/src/wallet/aptos/types.ts +278 -0
- package/src/wallet/bitcoin/adapter.ts +470 -0
- package/src/wallet/bitcoin/index.ts +38 -0
- package/src/wallet/bitcoin/mock.ts +516 -0
- package/src/wallet/bitcoin/types.ts +274 -0
- package/src/wallet/cosmos/adapter.ts +484 -0
- package/src/wallet/cosmos/index.ts +63 -0
- package/src/wallet/cosmos/mock.ts +596 -0
- package/src/wallet/cosmos/types.ts +462 -0
- package/src/wallet/index.ts +127 -0
- package/src/wallet/sui/adapter.ts +471 -0
- package/src/wallet/sui/index.ts +10 -0
- package/src/wallet/sui/mock.ts +439 -0
- package/src/wallet/sui/types.ts +245 -0
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aptos Wallet Adapter
|
|
3
|
+
*
|
|
4
|
+
* Implementation of WalletAdapter for Aptos blockchain.
|
|
5
|
+
* Supports Petra, Martian, Pontem, and other Aptos 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
|
+
AptosWalletProvider,
|
|
21
|
+
AptosAdapterConfig,
|
|
22
|
+
AptosWalletName,
|
|
23
|
+
AptosAccountInfo,
|
|
24
|
+
AptosTransaction,
|
|
25
|
+
AptosSignMessagePayload,
|
|
26
|
+
AptosSignMessageResponse,
|
|
27
|
+
} from './types'
|
|
28
|
+
import {
|
|
29
|
+
getAptosProvider,
|
|
30
|
+
aptosPublicKeyToHex,
|
|
31
|
+
getDefaultAptosRpcEndpoint,
|
|
32
|
+
} from './types'
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Aptos wallet adapter
|
|
36
|
+
*
|
|
37
|
+
* Provides SIP-compatible wallet interface for Aptos.
|
|
38
|
+
* Works with Petra, Martian, Pontem, and other Aptos wallets.
|
|
39
|
+
*
|
|
40
|
+
* @example Browser usage with Petra
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const wallet = new AptosWalletAdapter({ wallet: 'petra' })
|
|
43
|
+
* await wallet.connect()
|
|
44
|
+
*
|
|
45
|
+
* const balance = await wallet.getBalance()
|
|
46
|
+
* console.log(`Balance: ${balance} APT`)
|
|
47
|
+
*
|
|
48
|
+
* // Sign a message
|
|
49
|
+
* const sig = await wallet.signMessage(new TextEncoder().encode('Hello'))
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @example With custom RPC endpoint
|
|
53
|
+
* ```typescript
|
|
54
|
+
* const wallet = new AptosWalletAdapter({
|
|
55
|
+
* wallet: 'petra',
|
|
56
|
+
* network: 'testnet',
|
|
57
|
+
* rpcEndpoint: 'https://my-rpc.example.com',
|
|
58
|
+
* })
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export class AptosWalletAdapter extends BaseWalletAdapter {
|
|
62
|
+
readonly chain = 'aptos' as const
|
|
63
|
+
readonly name: string
|
|
64
|
+
|
|
65
|
+
private provider: AptosWalletProvider | undefined
|
|
66
|
+
private walletName: AptosWalletName
|
|
67
|
+
private network: string
|
|
68
|
+
private rpcEndpoint: string
|
|
69
|
+
|
|
70
|
+
// Event handler references for cleanup
|
|
71
|
+
private accountChangeHandler?: (account: AptosAccountInfo) => void
|
|
72
|
+
private networkChangeHandler?: (network: { networkName: string }) => void
|
|
73
|
+
private disconnectHandler?: () => void
|
|
74
|
+
|
|
75
|
+
constructor(config: AptosAdapterConfig = {}) {
|
|
76
|
+
super()
|
|
77
|
+
this.walletName = config.wallet ?? 'petra'
|
|
78
|
+
this.name = `aptos-${this.walletName}`
|
|
79
|
+
this.network = config.network ?? 'mainnet'
|
|
80
|
+
this.rpcEndpoint = config.rpcEndpoint ?? getDefaultAptosRpcEndpoint(this.network)
|
|
81
|
+
|
|
82
|
+
// Allow injecting provider for testing
|
|
83
|
+
if (config.provider) {
|
|
84
|
+
this.provider = config.provider
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Get the current Aptos network
|
|
90
|
+
*/
|
|
91
|
+
getNetwork(): string {
|
|
92
|
+
return this.network
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get the RPC endpoint
|
|
97
|
+
*/
|
|
98
|
+
getRpcEndpoint(): string {
|
|
99
|
+
return this.rpcEndpoint
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Set the RPC endpoint
|
|
104
|
+
*/
|
|
105
|
+
setRpcEndpoint(endpoint: string): void {
|
|
106
|
+
this.rpcEndpoint = endpoint
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Connect to the wallet
|
|
111
|
+
*/
|
|
112
|
+
async connect(): Promise<void> {
|
|
113
|
+
this._connectionState = 'connecting'
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
// Get provider if not already set
|
|
117
|
+
if (!this.provider) {
|
|
118
|
+
this.provider = getAptosProvider(this.walletName)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (!this.provider) {
|
|
122
|
+
this.setError(
|
|
123
|
+
WalletErrorCode.NOT_INSTALLED,
|
|
124
|
+
`${this.walletName} wallet is not installed`
|
|
125
|
+
)
|
|
126
|
+
throw new WalletError(
|
|
127
|
+
`${this.walletName} wallet is not installed`,
|
|
128
|
+
WalletErrorCode.NOT_INSTALLED
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Connect to wallet
|
|
133
|
+
const account = await this.provider.connect()
|
|
134
|
+
|
|
135
|
+
if (!account || !account.address) {
|
|
136
|
+
throw new WalletError(
|
|
137
|
+
'No account returned from wallet',
|
|
138
|
+
WalletErrorCode.CONNECTION_FAILED
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Set up event handlers
|
|
143
|
+
this.setupEventHandlers()
|
|
144
|
+
|
|
145
|
+
// Update state
|
|
146
|
+
const address = account.address
|
|
147
|
+
const hexPubKey = aptosPublicKeyToHex(account.publicKey)
|
|
148
|
+
this.setConnected(address, hexPubKey)
|
|
149
|
+
} catch (error) {
|
|
150
|
+
const message = error instanceof Error ? error.message : 'Connection failed'
|
|
151
|
+
|
|
152
|
+
// Check if user rejected
|
|
153
|
+
if (message.includes('User rejected') || message.includes('rejected') || message.includes('User disapproved')) {
|
|
154
|
+
this.setError(WalletErrorCode.CONNECTION_REJECTED, message)
|
|
155
|
+
throw new WalletError(message, WalletErrorCode.CONNECTION_REJECTED)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
this.setError(WalletErrorCode.CONNECTION_FAILED, message)
|
|
159
|
+
throw error instanceof WalletError
|
|
160
|
+
? error
|
|
161
|
+
: new WalletError(message, WalletErrorCode.CONNECTION_FAILED, { cause: error as Error })
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Disconnect from the wallet
|
|
167
|
+
*/
|
|
168
|
+
async disconnect(): Promise<void> {
|
|
169
|
+
this.cleanupEventHandlers()
|
|
170
|
+
|
|
171
|
+
if (this.provider?.disconnect) {
|
|
172
|
+
try {
|
|
173
|
+
await this.provider.disconnect()
|
|
174
|
+
} catch {
|
|
175
|
+
// Ignore disconnect errors
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
this.setDisconnected('User disconnected')
|
|
180
|
+
this.provider = undefined
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Sign a message
|
|
185
|
+
*/
|
|
186
|
+
async signMessage(message: Uint8Array): Promise<Signature> {
|
|
187
|
+
this.requireConnected()
|
|
188
|
+
|
|
189
|
+
if (!this.provider) {
|
|
190
|
+
throw new WalletError('Provider not available', WalletErrorCode.NOT_CONNECTED)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
try {
|
|
194
|
+
const messageStr = new TextDecoder().decode(message)
|
|
195
|
+
const nonce = Date.now().toString()
|
|
196
|
+
|
|
197
|
+
const payload: AptosSignMessagePayload = {
|
|
198
|
+
message: messageStr,
|
|
199
|
+
nonce,
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const response = await this.provider.signMessage(payload)
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
signature: (response.signature.startsWith('0x')
|
|
206
|
+
? response.signature
|
|
207
|
+
: `0x${response.signature}`) as HexString,
|
|
208
|
+
publicKey: this._publicKey as HexString,
|
|
209
|
+
}
|
|
210
|
+
} catch (error) {
|
|
211
|
+
const message = error instanceof Error ? error.message : 'Signing failed'
|
|
212
|
+
|
|
213
|
+
if (message.includes('User rejected') || message.includes('rejected') || message.includes('User disapproved')) {
|
|
214
|
+
throw new WalletError(message, WalletErrorCode.SIGNING_REJECTED)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
throw new WalletError(message, WalletErrorCode.SIGNING_FAILED, {
|
|
218
|
+
cause: error as Error,
|
|
219
|
+
})
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Sign a transaction
|
|
225
|
+
*
|
|
226
|
+
* The transaction data should be an AptosTransaction
|
|
227
|
+
*/
|
|
228
|
+
async signTransaction(tx: UnsignedTransaction): Promise<SignedTransaction> {
|
|
229
|
+
this.requireConnected()
|
|
230
|
+
|
|
231
|
+
if (!this.provider) {
|
|
232
|
+
throw new WalletError('Provider not available', WalletErrorCode.NOT_CONNECTED)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
try {
|
|
236
|
+
const aptosTx = tx.data as AptosTransaction
|
|
237
|
+
const signedBytes = await this.provider.signTransaction(aptosTx)
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
unsigned: tx,
|
|
241
|
+
signatures: [
|
|
242
|
+
{
|
|
243
|
+
signature: ('0x' + Buffer.from(signedBytes).toString('hex')) as HexString,
|
|
244
|
+
publicKey: this._publicKey as HexString,
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
serialized: ('0x' + Buffer.from(signedBytes).toString('hex')) as HexString,
|
|
248
|
+
}
|
|
249
|
+
} catch (error) {
|
|
250
|
+
const message = error instanceof Error ? error.message : 'Signing failed'
|
|
251
|
+
|
|
252
|
+
if (message.includes('User rejected') || message.includes('rejected') || message.includes('User disapproved')) {
|
|
253
|
+
throw new WalletError(message, WalletErrorCode.SIGNING_REJECTED)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
throw new WalletError(message, WalletErrorCode.SIGNING_FAILED, {
|
|
257
|
+
cause: error as Error,
|
|
258
|
+
})
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Sign and send a transaction
|
|
264
|
+
*/
|
|
265
|
+
async signAndSendTransaction(tx: UnsignedTransaction): Promise<TransactionReceipt> {
|
|
266
|
+
this.requireConnected()
|
|
267
|
+
|
|
268
|
+
if (!this.provider) {
|
|
269
|
+
throw new WalletError('Provider not available', WalletErrorCode.NOT_CONNECTED)
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
try {
|
|
273
|
+
const aptosTx = tx.data as AptosTransaction
|
|
274
|
+
const response = await this.provider.signAndSubmitTransaction(aptosTx)
|
|
275
|
+
|
|
276
|
+
return {
|
|
277
|
+
txHash: (response.hash.startsWith('0x')
|
|
278
|
+
? response.hash
|
|
279
|
+
: `0x${response.hash}`) as HexString,
|
|
280
|
+
status: 'pending', // Transaction is sent but not confirmed yet
|
|
281
|
+
timestamp: Date.now(),
|
|
282
|
+
}
|
|
283
|
+
} catch (error) {
|
|
284
|
+
const message = error instanceof Error ? error.message : 'Transaction failed'
|
|
285
|
+
|
|
286
|
+
if (message.includes('User rejected') || message.includes('rejected') || message.includes('User disapproved')) {
|
|
287
|
+
throw new WalletError(message, WalletErrorCode.TRANSACTION_REJECTED)
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (message.includes('insufficient') || message.includes('Insufficient')) {
|
|
291
|
+
throw new WalletError(message, WalletErrorCode.INSUFFICIENT_FUNDS)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
throw new WalletError(message, WalletErrorCode.TRANSACTION_FAILED, {
|
|
295
|
+
cause: error as Error,
|
|
296
|
+
})
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Get native APT balance (in Octas - 1 APT = 100,000,000 Octas)
|
|
302
|
+
*/
|
|
303
|
+
async getBalance(): Promise<bigint> {
|
|
304
|
+
this.requireConnected()
|
|
305
|
+
|
|
306
|
+
try {
|
|
307
|
+
const response = await fetch(`${this.rpcEndpoint}/accounts/${this._address}/resource/0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>`)
|
|
308
|
+
|
|
309
|
+
if (!response.ok) {
|
|
310
|
+
throw new Error(`Failed to fetch balance: ${response.statusText}`)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const data = await response.json()
|
|
314
|
+
const balance = data.data?.coin?.value ?? '0'
|
|
315
|
+
|
|
316
|
+
return BigInt(balance)
|
|
317
|
+
} catch (error) {
|
|
318
|
+
throw new WalletError(
|
|
319
|
+
'Failed to get balance',
|
|
320
|
+
WalletErrorCode.UNKNOWN,
|
|
321
|
+
{ cause: error as Error }
|
|
322
|
+
)
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Get token balance for a specific coin type
|
|
328
|
+
*/
|
|
329
|
+
async getTokenBalance(asset: Asset): Promise<bigint> {
|
|
330
|
+
this.requireConnected()
|
|
331
|
+
|
|
332
|
+
if (asset.chain !== 'aptos') {
|
|
333
|
+
throw new WalletError(
|
|
334
|
+
`Asset chain ${asset.chain} not supported by Aptos adapter`,
|
|
335
|
+
WalletErrorCode.UNSUPPORTED_CHAIN
|
|
336
|
+
)
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Native APT
|
|
340
|
+
if (!asset.address || asset.address === '0x1::aptos_coin::AptosCoin') {
|
|
341
|
+
return this.getBalance()
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
try {
|
|
345
|
+
const coinType = asset.address
|
|
346
|
+
const response = await fetch(`${this.rpcEndpoint}/accounts/${this._address}/resource/0x1::coin::CoinStore<${coinType}>`)
|
|
347
|
+
|
|
348
|
+
if (!response.ok) {
|
|
349
|
+
// Resource might not exist (no balance)
|
|
350
|
+
return 0n
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const data = await response.json()
|
|
354
|
+
const balance = data.data?.coin?.value ?? '0'
|
|
355
|
+
|
|
356
|
+
return BigInt(balance)
|
|
357
|
+
} catch {
|
|
358
|
+
// Token account might not exist
|
|
359
|
+
return 0n
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Set up wallet event handlers
|
|
365
|
+
*/
|
|
366
|
+
private setupEventHandlers(): void {
|
|
367
|
+
if (!this.provider) return
|
|
368
|
+
|
|
369
|
+
if (this.provider.onAccountChange) {
|
|
370
|
+
this.accountChangeHandler = (account: AptosAccountInfo) => {
|
|
371
|
+
const previousAddress = this._address
|
|
372
|
+
const newAddress = account.address
|
|
373
|
+
|
|
374
|
+
if (newAddress && newAddress !== previousAddress) {
|
|
375
|
+
this._address = newAddress
|
|
376
|
+
this._publicKey = aptosPublicKeyToHex(account.publicKey)
|
|
377
|
+
this.emitAccountChanged(previousAddress, newAddress)
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
this.provider.onAccountChange(this.accountChangeHandler)
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (this.provider.onNetworkChange) {
|
|
384
|
+
this.networkChangeHandler = (network: { networkName: string }) => {
|
|
385
|
+
const previousNetwork = this.network
|
|
386
|
+
this.network = network.networkName
|
|
387
|
+
// Update RPC endpoint if using default
|
|
388
|
+
if (!this.rpcEndpoint.includes('example')) {
|
|
389
|
+
this.rpcEndpoint = getDefaultAptosRpcEndpoint(this.network)
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
this.provider.onNetworkChange(this.networkChangeHandler)
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (this.provider.onDisconnect) {
|
|
396
|
+
this.disconnectHandler = () => {
|
|
397
|
+
this.setDisconnected('Wallet disconnected')
|
|
398
|
+
}
|
|
399
|
+
this.provider.onDisconnect(this.disconnectHandler)
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Clean up wallet event handlers
|
|
405
|
+
*/
|
|
406
|
+
private cleanupEventHandlers(): void {
|
|
407
|
+
// Note: Most Aptos wallets don't provide off() methods
|
|
408
|
+
// Event handlers will be cleaned up when provider is set to undefined
|
|
409
|
+
this.accountChangeHandler = undefined
|
|
410
|
+
this.networkChangeHandler = undefined
|
|
411
|
+
this.disconnectHandler = undefined
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Create an Aptos wallet adapter with default configuration
|
|
417
|
+
*/
|
|
418
|
+
export function createAptosAdapter(
|
|
419
|
+
config: AptosAdapterConfig = {}
|
|
420
|
+
): AptosWalletAdapter {
|
|
421
|
+
return new AptosWalletAdapter(config)
|
|
422
|
+
}
|