@lendasat/lendaswap-sdk-pure 0.2.8 → 0.2.10
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/README.md +125 -255
- package/dist/cctp/attestation.d.ts +35 -0
- package/dist/cctp/attestation.d.ts.map +1 -0
- package/dist/cctp/attestation.js +63 -0
- package/dist/cctp/attestation.js.map +1 -0
- package/dist/cctp/constants.d.ts +46 -0
- package/dist/cctp/constants.d.ts.map +1 -0
- package/dist/cctp/constants.js +80 -0
- package/dist/cctp/constants.js.map +1 -0
- package/dist/cctp/index.d.ts +13 -0
- package/dist/cctp/index.d.ts.map +1 -0
- package/dist/cctp/index.js +12 -0
- package/dist/cctp/index.js.map +1 -0
- package/dist/cctp/types.d.ts +44 -0
- package/dist/cctp/types.d.ts.map +1 -0
- package/dist/cctp/types.js +5 -0
- package/dist/cctp/types.js.map +1 -0
- package/dist/cctp/utils.d.ts +29 -0
- package/dist/cctp/utils.d.ts.map +1 -0
- package/dist/cctp/utils.js +50 -0
- package/dist/cctp/utils.js.map +1 -0
- package/dist/client.d.ts +129 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +320 -11
- package/dist/client.js.map +1 -1
- package/dist/create/arkade.d.ts.map +1 -1
- package/dist/create/arkade.js +2 -0
- package/dist/create/arkade.js.map +1 -1
- package/dist/create/bitcoin.d.ts.map +1 -1
- package/dist/create/bitcoin.js +2 -0
- package/dist/create/bitcoin.js.map +1 -1
- package/dist/create/index.d.ts +1 -1
- package/dist/create/index.d.ts.map +1 -1
- package/dist/create/lightning.d.ts.map +1 -1
- package/dist/create/lightning.js +2 -0
- package/dist/create/lightning.js.map +1 -1
- package/dist/create/types.d.ts +49 -3
- package/dist/create/types.d.ts.map +1 -1
- package/dist/evm/index.d.ts +1 -0
- package/dist/evm/index.d.ts.map +1 -1
- package/dist/evm/index.js +1 -0
- package/dist/evm/index.js.map +1 -1
- package/dist/evm/wallet.d.ts +164 -0
- package/dist/evm/wallet.d.ts.map +1 -0
- package/dist/evm/wallet.js +133 -0
- package/dist/evm/wallet.js.map +1 -0
- package/dist/generated/api.d.ts +44 -0
- package/dist/generated/api.d.ts.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/tokens.d.ts +90 -7
- package/dist/tokens.d.ts.map +1 -1
- package/dist/tokens.js +151 -13
- package/dist/tokens.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,28 +15,19 @@ This SDK supports the following swap directions:
|
|
|
15
15
|
|
|
16
16
|
### BTC to EVM
|
|
17
17
|
|
|
18
|
-
| Source
|
|
19
|
-
|
|
|
20
|
-
| Lightning
|
|
21
|
-
|
|
|
22
|
-
|
|
|
23
|
-
| Arkade | Polygon (USDC, USDT) | Supported |
|
|
24
|
-
| Arkade | Arbitrum (USDC, USDT) | Supported |
|
|
25
|
-
| Arkade | Ethereum (USDC, USDT, WBTC) | Supported |
|
|
26
|
-
| On-chain BTC | Polygon (USDC, USDT) | Supported |
|
|
27
|
-
| On-chain BTC | Arbitrum (USDC, USDT) | Supported |
|
|
28
|
-
| On-chain BTC | Ethereum (USDC, USDT, WBTC) | Supported |
|
|
18
|
+
| Source | Target | Status |
|
|
19
|
+
| --------- | --------------------------- | --------- |
|
|
20
|
+
| Lightning | Ethereum, Polygon, Arbitrum | Supported |
|
|
21
|
+
| Arkade | Ethereum, Polygon, Arbitrum | Supported |
|
|
22
|
+
| On-chain | Ethereum, Polygon, Arbitrum | Supported |
|
|
29
23
|
|
|
30
24
|
### EVM to BTC
|
|
31
25
|
|
|
32
26
|
| Source | Target | Status |
|
|
33
27
|
| --------------------------- | --------- | --------- |
|
|
34
|
-
| Polygon
|
|
35
|
-
| Polygon
|
|
36
|
-
|
|
|
37
|
-
| Arbitrum (USDC, USDT) | Lightning | Supported |
|
|
38
|
-
| Ethereum (USDC, USDT, WBTC) | Arkade | Supported |
|
|
39
|
-
| Ethereum (USDC, USDT, WBTC) | Lightning | Supported |
|
|
28
|
+
| Polygon, Arbitrus, Ethereum | Arkade | Supported |
|
|
29
|
+
| Polygon, Arbitrus, Ethereum | Lightning | Supported |
|
|
30
|
+
| Polygon, Arbitrus, Ethereum | On-chain | Supported |
|
|
40
31
|
|
|
41
32
|
**Refund support:**
|
|
42
33
|
|
|
@@ -50,13 +41,12 @@ This SDK supports the following swap directions:
|
|
|
50
41
|
### Setup
|
|
51
42
|
|
|
52
43
|
```typescript
|
|
53
|
-
import {
|
|
44
|
+
import {Client, IdbWalletStorage, IdbSwapStorage} from "@lendasat/lendaswap-sdk-pure";
|
|
54
45
|
|
|
55
46
|
// Create a client with persistent storage (browser)
|
|
56
47
|
const client = await Client.builder()
|
|
57
48
|
.withSignerStorage(new IdbWalletStorage())
|
|
58
49
|
.withSwapStorage(new IdbSwapStorage())
|
|
59
|
-
.withApiKey("your-api-key")
|
|
60
50
|
.build();
|
|
61
51
|
|
|
62
52
|
// Or import an existing wallet
|
|
@@ -70,290 +60,178 @@ const client = await Client.builder()
|
|
|
70
60
|
const mnemonic = client.getMnemonic();
|
|
71
61
|
```
|
|
72
62
|
|
|
73
|
-
###
|
|
63
|
+
### Quotes
|
|
74
64
|
|
|
75
65
|
```typescript
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
//
|
|
80
|
-
|
|
66
|
+
import { Asset } from "@lendasat/lendaswap-sdk-pure";
|
|
67
|
+
|
|
68
|
+
const quote = await client.getQuote({
|
|
69
|
+
sourceChain: Asset.BTC_ARKADE.chain, // "Arkade"
|
|
70
|
+
sourceToken: Asset.BTC_ARKADE.tokenId, // "btc"
|
|
71
|
+
targetChain: Asset.USDC_POLYGON.chain, // "137"
|
|
72
|
+
targetToken: Asset.USDC_POLYGON.tokenId, // "0x3c499c..."
|
|
73
|
+
sourceAmount: 100_000, // sats
|
|
74
|
+
});
|
|
81
75
|
console.log(`You'll receive: ${quote.target_amount} USDC`);
|
|
82
76
|
```
|
|
83
77
|
|
|
84
78
|
### Create a Swap
|
|
85
79
|
|
|
86
|
-
|
|
80
|
+
Use `createSwap` for all swap directions. The SDK routes automatically based on the source/target asset:
|
|
87
81
|
|
|
88
82
|
```typescript
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
83
|
+
// BTC → EVM: Arkade to USDC on Polygon
|
|
84
|
+
const result = await client.createSwap({
|
|
85
|
+
source: Asset.BTC_ARKADE,
|
|
86
|
+
target: Asset.USDC_POLYGON,
|
|
87
|
+
sourceAmount: 100_000, // sats
|
|
88
|
+
targetAddress: "0x...", // your EVM address
|
|
94
89
|
});
|
|
95
90
|
|
|
96
|
-
//
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
91
|
+
// EVM → BTC: USDC on Polygon to Arkade
|
|
92
|
+
const result = await client.createSwap({
|
|
93
|
+
source: Asset.USDC_POLYGON,
|
|
94
|
+
target: Asset.BTC_ARKADE,
|
|
95
|
+
sourceAmount: 10_000_000, // 10 USDC (6 decimals)
|
|
96
|
+
targetAddress: "ark1...", // your Arkade address
|
|
97
|
+
userAddress: "0x...", // your EVM wallet address (required for EVM-sourced swaps)
|
|
98
|
+
});
|
|
102
99
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
evmChainId: 137,
|
|
109
|
-
sourceAmount: 100000, // sats
|
|
100
|
+
// Or use any token by chain + contract address
|
|
101
|
+
const result = await client.createSwap({
|
|
102
|
+
source: { chain: "42161", tokenId: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831" }, // USDC on Arbitrum
|
|
103
|
+
target: Asset.BTC_LIGHTNING,
|
|
104
|
+
targetAddress: "lnbc...", // BOLT11 invoice
|
|
110
105
|
});
|
|
111
106
|
|
|
112
|
-
|
|
113
|
-
console.log(`Send BTC to: ${result.response.btc_vhtlc_address}`);
|
|
114
|
-
console.log(`Swap ID: ${result.response.id}`);
|
|
115
|
-
|
|
116
|
-
// Once the server has funded the EVM HTLC (status: "serverfunded"),
|
|
117
|
-
// claim gaslessly — the server submits the tx on your behalf:
|
|
118
|
-
const claimResult = await client.claimViaGasless(
|
|
119
|
-
result.response.id,
|
|
120
|
-
async (digest) => {
|
|
121
|
-
// Sign the EIP-712 digest with your EVM wallet
|
|
122
|
-
// e.g. using ethers.js: wallet.signMessage(ethers.getBytes(digest))
|
|
123
|
-
return { v: 27, r: "0x...", s: "0x..." };
|
|
124
|
-
},
|
|
125
|
-
"0x1234567890abcdef1234567890abcdef12345678", // destination
|
|
126
|
-
);
|
|
127
|
-
console.log(`Claimed! TX: ${claimResult.txHash}`);
|
|
107
|
+
const swapId = result.response.id;
|
|
128
108
|
```
|
|
129
109
|
|
|
130
|
-
|
|
110
|
+
### Fund EVM-Sourced Swaps
|
|
111
|
+
|
|
112
|
+
EVM-sourced swaps need to be funded after creation. The SDK handles the full Permit2 flow (allowance check, ERC-20
|
|
113
|
+
approval, EIP-712 signing, transaction submission) in a single call:
|
|
131
114
|
|
|
132
115
|
```typescript
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
tokenAddress: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", // USDC on Polygon
|
|
136
|
-
evmChainId: 137,
|
|
137
|
-
sourceAmount: 100000, // sats
|
|
138
|
-
});
|
|
116
|
+
// Fund with an external wallet
|
|
117
|
+
const {txHash} = await client.fundSwap(swapId, signer);
|
|
139
118
|
|
|
140
|
-
//
|
|
141
|
-
|
|
142
|
-
console.log(`Swap ID: ${result.response.id}`);
|
|
119
|
+
// Or fund gaslessly (SDK signs internally, server submits via relay)
|
|
120
|
+
const {txHash} = await client.fundSwapGasless(swapId);
|
|
143
121
|
```
|
|
144
122
|
|
|
145
|
-
|
|
123
|
+
### The EvmSigner Interface
|
|
146
124
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
targetAddress: "ark1...", // Your Arkade address
|
|
150
|
-
tokenAddress: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", // USDC on Polygon
|
|
151
|
-
evmChainId: 137,
|
|
152
|
-
userAddress: "0x...", // Your EVM wallet address
|
|
153
|
-
sourceAmount: 100000000n, // Amount in token's smallest unit (e.g., 6 decimals for USDC)
|
|
154
|
-
});
|
|
125
|
+
`EvmSigner` is a minimal wallet abstraction. Implement it once for your stack — the SDK stays free of EVM library
|
|
126
|
+
dependencies:
|
|
155
127
|
|
|
156
|
-
|
|
157
|
-
|
|
128
|
+
```typescript
|
|
129
|
+
import type {EvmSigner} from "@lendasat/lendaswap-sdk-pure";
|
|
158
130
|
```
|
|
159
131
|
|
|
160
|
-
|
|
132
|
+
**wagmi / viem:**
|
|
161
133
|
|
|
162
134
|
```typescript
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
135
|
+
import {createPublicClient, http} from "viem";
|
|
136
|
+
|
|
137
|
+
const publicClient = createPublicClient({chain, transport: http()});
|
|
138
|
+
|
|
139
|
+
const signer: EvmSigner = {
|
|
140
|
+
address: walletClient.account.address,
|
|
141
|
+
chainId: chain.id,
|
|
142
|
+
signTypedData: (td) =>
|
|
143
|
+
walletClient.signTypedData({...td, account: walletClient.account}),
|
|
144
|
+
sendTransaction: (tx) =>
|
|
145
|
+
walletClient.sendTransaction({to: tx.to, data: tx.data, chain, gas: tx.gas}),
|
|
146
|
+
waitForReceipt: (hash) =>
|
|
147
|
+
publicClient.waitForTransactionReceipt({hash}).then((r) => ({
|
|
148
|
+
status: r.status,
|
|
149
|
+
blockNumber: r.blockNumber,
|
|
150
|
+
transactionHash: r.transactionHash,
|
|
151
|
+
})),
|
|
152
|
+
getTransaction: (hash) =>
|
|
153
|
+
publicClient.getTransaction({hash}).then((tx) => ({
|
|
154
|
+
to: tx.to ?? null, input: tx.input, from: tx.from,
|
|
155
|
+
})),
|
|
156
|
+
call: (tx) =>
|
|
157
|
+
publicClient.call({to: tx.to, data: tx.data, account: tx.from, blockNumber: tx.blockNumber})
|
|
158
|
+
.then((r) => r.data ?? "0x"),
|
|
159
|
+
};
|
|
172
160
|
```
|
|
173
161
|
|
|
174
|
-
|
|
162
|
+
**ethers.js v6:**
|
|
175
163
|
|
|
176
164
|
```typescript
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
})
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
165
|
+
const signer: EvmSigner = {
|
|
166
|
+
address: await wallet.getAddress(),
|
|
167
|
+
chainId: Number((await wallet.provider.getNetwork()).chainId),
|
|
168
|
+
signTypedData: (td) =>
|
|
169
|
+
wallet.signTypedData(td.domain, td.types, td.message),
|
|
170
|
+
sendTransaction: (tx) =>
|
|
171
|
+
wallet.sendTransaction({to: tx.to, data: tx.data, gasLimit: tx.gas})
|
|
172
|
+
.then((r) => r.hash),
|
|
173
|
+
waitForReceipt: (hash) =>
|
|
174
|
+
wallet.provider.waitForTransaction(hash).then((r) => ({
|
|
175
|
+
status: r.status === 1 ? "success" : "reverted",
|
|
176
|
+
blockNumber: BigInt(r.blockNumber),
|
|
177
|
+
transactionHash: r.hash,
|
|
178
|
+
})
|
|
179
|
+
),
|
|
180
|
+
getTransaction: (hash) =>
|
|
181
|
+
wallet.provider.getTransaction(hash).then((tx) => ({
|
|
182
|
+
to: tx.to, input: tx.data, from: tx.from,
|
|
183
|
+
})),
|
|
184
|
+
call: (tx) =>
|
|
185
|
+
wallet.provider.call({to: tx.to, data: tx.data, from: tx.from, blockTag: tx.blockNumber}),
|
|
186
|
+
};
|
|
187
187
|
```
|
|
188
188
|
|
|
189
189
|
### Monitor Swap Status
|
|
190
190
|
|
|
191
191
|
```typescript
|
|
192
|
-
|
|
193
|
-
const swap = await client.getSwap("swap-uuid");
|
|
192
|
+
const swap = await client.getSwap(swapId);
|
|
194
193
|
console.log(`Status: ${swap.status}`);
|
|
195
194
|
|
|
196
|
-
// Status flow: pending
|
|
195
|
+
// Status flow: pending → clientfunded → serverfunded → clientredeemed → serverredeemed
|
|
197
196
|
```
|
|
198
197
|
|
|
199
|
-
### Claim
|
|
198
|
+
### Claim
|
|
200
199
|
|
|
201
|
-
|
|
200
|
+
For BTC-to-EVM swaps, once the server has funded the EVM HTLC (`serverfunded`), claim your tokens:
|
|
202
201
|
|
|
203
202
|
```typescript
|
|
204
|
-
|
|
205
|
-
const claimResult = await client.claimViaGasless(
|
|
206
|
-
"swap-uuid",
|
|
207
|
-
async (digest) => {
|
|
208
|
-
// Sign the EIP-712 digest with your EVM wallet
|
|
209
|
-
return { v: 27, r: "0x...", s: "0x..." };
|
|
210
|
-
},
|
|
211
|
-
"0xYourDestinationAddress",
|
|
212
|
-
);
|
|
213
|
-
console.log(`Claim tx: ${claimResult.txHash}`);
|
|
214
|
-
|
|
215
|
-
// For other swap types (Lightning/On-chain to EVM), use the existing claim:
|
|
216
|
-
const result = await client.claim("swap-uuid");
|
|
203
|
+
const result = await client.claim(swapId);
|
|
217
204
|
```
|
|
218
205
|
|
|
219
|
-
### Refund
|
|
206
|
+
### Refund
|
|
220
207
|
|
|
221
|
-
|
|
222
|
-
// For on-chain BTC swaps
|
|
223
|
-
const refundResult = await client.refundSwap("swap-uuid", {
|
|
224
|
-
destinationAddress: "bc1q...", // Your Bitcoin address
|
|
225
|
-
feeRateSatPerVb: 5,
|
|
226
|
-
});
|
|
208
|
+
If a swap times out, refund your funds:
|
|
227
209
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
210
|
+
```typescript
|
|
211
|
+
// BTC swaps (on-chain or Arkade)
|
|
212
|
+
const result = await client.refundSwap(swapId, {
|
|
213
|
+
destinationAddress: "bc1q...", // or "ark1..."
|
|
231
214
|
});
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
### Storage
|
|
235
|
-
|
|
236
|
-
The SDK provides pluggable storage interfaces for persisting wallet and swap data.
|
|
237
|
-
Browser storage uses [Dexie](https://dexie.org/) for IndexedDB access with the database name `lendaswap-v3`.
|
|
238
|
-
|
|
239
|
-
**Storage Types:**
|
|
240
215
|
|
|
241
|
-
|
|
242
|
-
|
|
216
|
+
// EVM swaps — manual refund (after timelock expires, user pays gas)
|
|
217
|
+
const {txHash} = await client.refundEvmWithSigner(swapId, signer, "direct");
|
|
243
218
|
|
|
244
|
-
|
|
219
|
+
// EVM swaps — collaborative refund (instant, gasless, server cosigns)
|
|
220
|
+
const {txHash} = await client.collabRefundEvmWithSigner(swapId, signer, "swap-back");
|
|
245
221
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
```typescript
|
|
249
|
-
interface StoredSwap {
|
|
250
|
-
version: number; // Schema version for migrations
|
|
251
|
-
swapId: string; // Primary key
|
|
252
|
-
keyIndex: number; // Key derivation index
|
|
253
|
-
response: GetSwapResponse; // Full API response
|
|
254
|
-
publicKey: string; // Hex-encoded compressed public key
|
|
255
|
-
preimage: string; // Hex-encoded preimage for claiming HTLCs
|
|
256
|
-
preimageHash: string; // Hex-encoded hash lock
|
|
257
|
-
secretKey: string; // Hex-encoded secret key for signing
|
|
258
|
-
storedAt: number; // Timestamp when first stored
|
|
259
|
-
updatedAt: number; // Timestamp when last updated
|
|
260
|
-
}
|
|
222
|
+
// EVM swaps — collaborative refund for gasless swaps (SDK signs internally)
|
|
223
|
+
const {txHash} = await client.collabRefundEvmSwap(swapId, "swap-back");
|
|
261
224
|
```
|
|
262
225
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
```typescript
|
|
266
|
-
import {
|
|
267
|
-
InMemoryWalletStorage,
|
|
268
|
-
InMemorySwapStorage,
|
|
269
|
-
IdbWalletStorage, // Browser only (IndexedDB via Dexie)
|
|
270
|
-
IdbSwapStorage, // Browser only (IndexedDB via Dexie)
|
|
271
|
-
idbStorageFactory, // Factory for creating IDB storage
|
|
272
|
-
inMemoryStorageFactory,
|
|
273
|
-
SWAP_STORAGE_VERSION,
|
|
274
|
-
type StoredSwap,
|
|
275
|
-
} from "@lendasat/lendaswap-sdk-pure";
|
|
276
|
-
|
|
277
|
-
// In-memory storage (for testing or temporary sessions)
|
|
278
|
-
const walletStorage = new InMemoryWalletStorage();
|
|
279
|
-
const swapStorage = new InMemorySwapStorage();
|
|
280
|
-
|
|
281
|
-
// IndexedDB storage (for browser persistence)
|
|
282
|
-
// Uses shared "lendaswap-v3" database with "wallet" and "swaps" tables
|
|
283
|
-
const walletStorage = new IdbWalletStorage();
|
|
284
|
-
const swapStorage = new IdbSwapStorage();
|
|
285
|
-
|
|
286
|
-
// Store a swap
|
|
287
|
-
await swapStorage.store({
|
|
288
|
-
version: SWAP_STORAGE_VERSION,
|
|
289
|
-
swapId: "uuid",
|
|
290
|
-
keyIndex: 0,
|
|
291
|
-
response: apiResponse,
|
|
292
|
-
publicKey: "02...",
|
|
293
|
-
preimage: "...",
|
|
294
|
-
preimageHash: "...",
|
|
295
|
-
secretKey: "...",
|
|
296
|
-
storedAt: Date.now(),
|
|
297
|
-
updatedAt: Date.now(),
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
// Update swap response (e.g., after polling for status)
|
|
301
|
-
await swapStorage.update("uuid", newApiResponse);
|
|
302
|
-
|
|
303
|
-
// Custom storage (implement the WalletStorage/SwapStorage interfaces)
|
|
304
|
-
// For React Native, you might use AsyncStorage or SQLite
|
|
305
|
-
```
|
|
226
|
+
Refund mode controls what token you receive:
|
|
306
227
|
|
|
307
|
-
|
|
228
|
+
- `"direct"` — refund as WBTC/TBTC (the HTLC lock token)
|
|
229
|
+
- `"swap-back"` — refund as the original source token (e.g., USDC) via DEX swap
|
|
308
230
|
|
|
309
|
-
###
|
|
231
|
+
### Storage
|
|
310
232
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
├── api/
|
|
314
|
-
│ └── client.ts # Low-level API client wrapper
|
|
315
|
-
├── generated/
|
|
316
|
-
│ └── api.ts # Auto-generated types from OpenAPI spec
|
|
317
|
-
├── create/
|
|
318
|
-
│ ├── index.ts # Swap creation exports
|
|
319
|
-
│ ├── types.ts # Type definitions for swap creation
|
|
320
|
-
│ ├── arkade.ts # Arkade-to-EVM swap creation
|
|
321
|
-
│ ├── bitcoin.ts # Bitcoin-to-EVM swap creation
|
|
322
|
-
│ ├── bitcoin-to-arkade.ts # Bitcoin-to-Arkade swap creation
|
|
323
|
-
│ ├── evm-to-arkade.ts # EVM-to-Arkade swap creation
|
|
324
|
-
│ ├── evm-to-bitcoin.ts # EVM-to-Bitcoin swap creation
|
|
325
|
-
│ ├── evm-to-lightning.ts # EVM-to-Lightning swap creation
|
|
326
|
-
│ └── lightning.ts # Lightning-to-EVM swap creation
|
|
327
|
-
├── redeem/
|
|
328
|
-
│ ├── index.ts # Claim/redeem operation exports
|
|
329
|
-
│ ├── arkade.ts # Arkade claim logic
|
|
330
|
-
│ ├── ethereum.ts # Ethereum claim logic
|
|
331
|
-
│ └── gasless.ts # Gasless claim logic
|
|
332
|
-
├── refund/
|
|
333
|
-
│ ├── index.ts # Refund operation exports
|
|
334
|
-
│ ├── arkade.ts # Arkade refund logic
|
|
335
|
-
│ └── onchain.ts # On-chain refund logic
|
|
336
|
-
├── evm/
|
|
337
|
-
│ ├── index.ts # EVM HTLC utilities
|
|
338
|
-
│ ├── coordinator.ts # Coordinator interaction
|
|
339
|
-
│ ├── htlc.ts # HTLC contract utilities
|
|
340
|
-
│ └── signing.ts # EVM signing utilities
|
|
341
|
-
├── signer/
|
|
342
|
-
│ └── index.ts # HD wallet key derivation (BIP39/BIP32)
|
|
343
|
-
├── storage/
|
|
344
|
-
│ ├── index.ts # Storage interfaces and in-memory implementations
|
|
345
|
-
│ ├── idb.ts # IndexedDB storage for browsers
|
|
346
|
-
│ ├── sqlite.ts # SQLite storage for Node.js
|
|
347
|
-
│ └── types.ts # StoredSwap type definition
|
|
348
|
-
├── client.ts # High-level Client class with convenience methods
|
|
349
|
-
├── arkade.ts # Arkade VHTLC query utilities
|
|
350
|
-
├── delegate.ts # Delegate settlement utilities
|
|
351
|
-
├── tokens.ts # Token helpers and constants
|
|
352
|
-
├── usd-price.ts # USD price fetching via CoinGecko
|
|
353
|
-
├── price-calculations.ts # Price calculation utilities
|
|
354
|
-
├── node.ts # Node.js-specific exports (SQLite storage)
|
|
355
|
-
└── index.ts # Public exports
|
|
356
|
-
```
|
|
233
|
+
The SDK provides pluggable storage interfaces for persisting wallet and swap data.
|
|
234
|
+
Browser storage uses [Dexie](https://dexie.org/) for IndexedDB access with the database name `lendaswap-v3`.
|
|
357
235
|
|
|
358
236
|
### Auto-generated API Types
|
|
359
237
|
|
|
@@ -402,11 +280,3 @@ When adding new functionality:
|
|
|
402
280
|
1. **API methods**: Add convenience methods to `src/client.ts` that wrap the low-level API calls
|
|
403
281
|
2. **New types**: If the backend adds new endpoints, regenerate the API types first
|
|
404
282
|
3. **Exports**: Update `src/index.ts` to export any new public types or classes
|
|
405
|
-
|
|
406
|
-
### Dependencies
|
|
407
|
-
|
|
408
|
-
- `openapi-fetch` - Type-safe HTTP client for OpenAPI specs
|
|
409
|
-
- `@noble/hashes` - Cryptographic hash functions
|
|
410
|
-
- `@scure/bip32` - BIP32 HD wallet derivation
|
|
411
|
-
- `@scure/bip39` - BIP39 mnemonic phrase handling
|
|
412
|
-
- `dexie` - IndexedDB wrapper for browser storage
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CCTP attestation client.
|
|
3
|
+
*
|
|
4
|
+
* Polls Circle's IRIS API for attestations after a USDC burn.
|
|
5
|
+
* Used on the destination chain to call MessageTransmitter.receiveMessage().
|
|
6
|
+
*/
|
|
7
|
+
import { type CctpChainName } from "./constants.js";
|
|
8
|
+
export interface FetchAttestationOptions {
|
|
9
|
+
/** Source chain name (e.g. "Polygon"). */
|
|
10
|
+
sourceChain: CctpChainName;
|
|
11
|
+
/** Transaction hash of the burn on the source chain. */
|
|
12
|
+
txHash: string;
|
|
13
|
+
/** IRIS API base URL. Defaults to mainnet. */
|
|
14
|
+
irisApiUrl?: string;
|
|
15
|
+
/** Polling interval in ms. Defaults to 10000 (10s). */
|
|
16
|
+
pollIntervalMs?: number;
|
|
17
|
+
/** Maximum time to wait in ms. Defaults to 900000 (15min). */
|
|
18
|
+
timeoutMs?: number;
|
|
19
|
+
/** Optional abort signal. */
|
|
20
|
+
signal?: AbortSignal;
|
|
21
|
+
}
|
|
22
|
+
export interface AttestationResult {
|
|
23
|
+
/** Raw CCTP message bytes (hex with 0x prefix). */
|
|
24
|
+
message: string;
|
|
25
|
+
/** Attestation signature bytes (hex with 0x prefix). */
|
|
26
|
+
attestation: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Poll the IRIS V2 API until the attestation is ready for a given burn tx.
|
|
30
|
+
*
|
|
31
|
+
* @returns The message and attestation bytes needed to call receiveMessage().
|
|
32
|
+
* @throws If the attestation is not ready within the timeout, or the request fails.
|
|
33
|
+
*/
|
|
34
|
+
export declare function fetchAttestation(options: FetchAttestationOptions): Promise<AttestationResult>;
|
|
35
|
+
//# sourceMappingURL=attestation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attestation.d.ts","sourceRoot":"","sources":["../../src/cctp/attestation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,KAAK,aAAa,EAEnB,MAAM,gBAAgB,CAAC;AAGxB,MAAM,WAAW,uBAAuB;IACtC,0CAA0C;IAC1C,WAAW,EAAE,aAAa,CAAC;IAC3B,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CA4D5B"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CCTP attestation client.
|
|
3
|
+
*
|
|
4
|
+
* Polls Circle's IRIS API for attestations after a USDC burn.
|
|
5
|
+
* Used on the destination chain to call MessageTransmitter.receiveMessage().
|
|
6
|
+
*/
|
|
7
|
+
import { CCTP_DOMAINS, IRIS_API_MAINNET, } from "./constants.js";
|
|
8
|
+
/**
|
|
9
|
+
* Poll the IRIS V2 API until the attestation is ready for a given burn tx.
|
|
10
|
+
*
|
|
11
|
+
* @returns The message and attestation bytes needed to call receiveMessage().
|
|
12
|
+
* @throws If the attestation is not ready within the timeout, or the request fails.
|
|
13
|
+
*/
|
|
14
|
+
export async function fetchAttestation(options) {
|
|
15
|
+
const { sourceChain, txHash, irisApiUrl = IRIS_API_MAINNET, pollIntervalMs = 10_000, timeoutMs = 900_000, signal, } = options;
|
|
16
|
+
const sourceDomain = CCTP_DOMAINS[sourceChain];
|
|
17
|
+
if (sourceDomain === undefined) {
|
|
18
|
+
throw new Error(`Unknown CCTP source chain: ${sourceChain}`);
|
|
19
|
+
}
|
|
20
|
+
const url = `${irisApiUrl}/v2/messages/${sourceDomain}?transactionHash=${txHash}`;
|
|
21
|
+
const startTime = Date.now();
|
|
22
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
23
|
+
signal?.throwIfAborted();
|
|
24
|
+
try {
|
|
25
|
+
const response = await fetch(url);
|
|
26
|
+
if (response.status === 404) {
|
|
27
|
+
// Message not yet indexed, keep polling
|
|
28
|
+
await sleep(pollIntervalMs, signal);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
throw new Error(`IRIS API error: ${response.status} ${response.statusText}`);
|
|
33
|
+
}
|
|
34
|
+
const data = await response.json();
|
|
35
|
+
if (data.messages.length > 0 && data.messages[0].status === "complete") {
|
|
36
|
+
return {
|
|
37
|
+
message: data.messages[0].message,
|
|
38
|
+
attestation: data.messages[0].attestation,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
// Attestation pending, keep polling
|
|
42
|
+
await sleep(pollIntervalMs, signal);
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
46
|
+
throw err;
|
|
47
|
+
}
|
|
48
|
+
// Network errors — retry after delay
|
|
49
|
+
await sleep(pollIntervalMs, signal);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
throw new Error(`Attestation not ready after ${timeoutMs / 1000}s for tx ${txHash} on ${sourceChain}`);
|
|
53
|
+
}
|
|
54
|
+
function sleep(ms, signal) {
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
const timer = setTimeout(resolve, ms);
|
|
57
|
+
signal?.addEventListener("abort", () => {
|
|
58
|
+
clearTimeout(timer);
|
|
59
|
+
reject(new DOMException("Aborted", "AbortError"));
|
|
60
|
+
}, { once: true });
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=attestation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attestation.js","sourceRoot":"","sources":["../../src/cctp/attestation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,YAAY,EAEZ,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAyBxB;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAgC;IAEhC,MAAM,EACJ,WAAW,EACX,MAAM,EACN,UAAU,GAAG,gBAAgB,EAC7B,cAAc,GAAG,MAAM,EACvB,SAAS,GAAG,OAAO,EACnB,MAAM,GACP,GAAG,OAAO,CAAC;IAEZ,MAAM,YAAY,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;IAC/C,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,8BAA8B,WAAW,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,GAAG,GAAG,GAAG,UAAU,gBAAgB,YAAY,oBAAoB,MAAM,EAAE,CAAC;IAElF,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,SAAS,EAAE,CAAC;QAC1C,MAAM,EAAE,cAAc,EAAE,CAAC;QAEzB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;YAElC,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,wCAAwC;gBACxC,MAAM,KAAK,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;gBACpC,SAAS;YACX,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CACb,mBAAmB,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAC5D,CAAC;YACJ,CAAC;YAED,MAAM,IAAI,GAAwB,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAExD,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;gBACvE,OAAO;oBACL,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO;oBACjC,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW;iBAC1C,CAAC;YACJ,CAAC;YAED,oCAAoC;YACpC,MAAM,KAAK,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,YAAY,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC7D,MAAM,GAAG,CAAC;YACZ,CAAC;YACD,qCAAqC;YACrC,MAAM,KAAK,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CACb,+BAA+B,SAAS,GAAG,IAAI,YAAY,MAAM,OAAO,WAAW,EAAE,CACtF,CAAC;AACJ,CAAC;AAED,SAAS,KAAK,CAAC,EAAU,EAAE,MAAoB;IAC7C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACtC,MAAM,EAAE,gBAAgB,CACtB,OAAO,EACP,GAAG,EAAE;YACH,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,IAAI,YAAY,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;QACpD,CAAC,EACD,EAAE,IAAI,EAAE,IAAI,EAAE,CACf,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CCTP (Cross-Chain Transfer Protocol) constants.
|
|
3
|
+
*
|
|
4
|
+
* Uses CCTP V2 contracts which share the same address across all EVM chains.
|
|
5
|
+
* See: https://developers.circle.com/cctp/references/contract-addresses
|
|
6
|
+
*/
|
|
7
|
+
export declare const TOKEN_MESSENGER_V2 = "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d";
|
|
8
|
+
export declare const MESSAGE_TRANSMITTER_V2 = "0x81D40F21F12A8F0E3252Bccb954D722d4c464B64";
|
|
9
|
+
export declare const CCTP_DOMAINS: {
|
|
10
|
+
readonly Ethereum: 0;
|
|
11
|
+
readonly Avalanche: 1;
|
|
12
|
+
readonly Optimism: 2;
|
|
13
|
+
readonly Arbitrum: 3;
|
|
14
|
+
readonly Solana: 5;
|
|
15
|
+
readonly Base: 6;
|
|
16
|
+
readonly Polygon: 7;
|
|
17
|
+
readonly Unichain: 10;
|
|
18
|
+
readonly Linea: 11;
|
|
19
|
+
readonly Sonic: 13;
|
|
20
|
+
readonly "World Chain": 14;
|
|
21
|
+
readonly Monad: 15;
|
|
22
|
+
readonly Sei: 16;
|
|
23
|
+
readonly HyperEVM: 19;
|
|
24
|
+
readonly Ink: 21;
|
|
25
|
+
};
|
|
26
|
+
export type CctpChainName = keyof typeof CCTP_DOMAINS;
|
|
27
|
+
export declare const USDC_ADDRESSES: Record<string, string>;
|
|
28
|
+
export declare const TOKEN_MESSENGER_ADDRESSES: Record<string, string>;
|
|
29
|
+
export declare const MESSAGE_TRANSMITTER_ADDRESSES: Record<string, string>;
|
|
30
|
+
/**
|
|
31
|
+
* Magic hookData for Circle's Forwarding Service.
|
|
32
|
+
* Encodes "cctp-forward" + version 0 + data length 0.
|
|
33
|
+
* When passed to depositForBurnWithHook, Circle auto-mints on destination — zero gas needed.
|
|
34
|
+
*/
|
|
35
|
+
export declare const FORWARDING_SERVICE_HOOK_DATA = "0x636374702d666f72776172640000000000000000000000000000000000000000";
|
|
36
|
+
/** Fast transfer finality threshold. */
|
|
37
|
+
export declare const FINALITY_FAST = 1000;
|
|
38
|
+
/** Standard transfer finality threshold. */
|
|
39
|
+
export declare const FINALITY_STANDARD = 2000;
|
|
40
|
+
/** Forwarding fee for Ethereum destination ($1.25 in USDC units). */
|
|
41
|
+
export declare const FORWARDING_FEE_ETHEREUM = 1250000n;
|
|
42
|
+
/** Forwarding fee for all other destinations ($0.20 in USDC units). */
|
|
43
|
+
export declare const FORWARDING_FEE_OTHER = 200000n;
|
|
44
|
+
export declare const IRIS_API_MAINNET = "https://iris-api.circle.com";
|
|
45
|
+
export declare const IRIS_API_TESTNET = "https://iris-api-sandbox.circle.com";
|
|
46
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/cctp/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,eAAO,MAAM,kBAAkB,+CAA+C,CAAC;AAC/E,eAAO,MAAM,sBAAsB,+CACW,CAAC;AAO/C,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;CAgBf,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,YAAY,CAAC;AAMtD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAejD,CAAC;AAOF,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAG1D,CAAC;AAEJ,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAG9D,CAAC;AAMJ;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,uEAC6B,CAAC;AAEvE,wCAAwC;AACxC,eAAO,MAAM,aAAa,OAAO,CAAC;AAClC,4CAA4C;AAC5C,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC,qEAAqE;AACrE,eAAO,MAAM,uBAAuB,WAAa,CAAC;AAClD,uEAAuE;AACvE,eAAO,MAAM,oBAAoB,UAAW,CAAC;AAM7C,eAAO,MAAM,gBAAgB,gCAAgC,CAAC;AAC9D,eAAO,MAAM,gBAAgB,wCAAwC,CAAC"}
|