@atomiqlabs/chain-starknet 8.1.11 → 8.2.2
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 +74 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.js +72 -3
- package/dist/node/index.d.ts +10 -0
- package/dist/node/index.js +15 -0
- package/dist/starknet/StarknetInitializer.d.ts +39 -6
- package/dist/starknet/StarknetInitializer.js +3 -3
- package/dist/starknet/btcrelay/StarknetBtcRelay.d.ts +7 -6
- package/dist/starknet/btcrelay/StarknetBtcRelay.js +8 -8
- package/dist/starknet/btcrelay/headers/StarknetBtcHeader.d.ts +2 -0
- package/dist/starknet/btcrelay/headers/StarknetBtcHeader.js +2 -0
- package/dist/starknet/btcrelay/headers/StarknetBtcStoredHeader.d.ts +3 -1
- package/dist/starknet/btcrelay/headers/StarknetBtcStoredHeader.js +3 -1
- package/dist/starknet/chain/StarknetAction.js +1 -1
- package/dist/starknet/chain/StarknetChainInterface.d.ts +25 -0
- package/dist/starknet/chain/StarknetChainInterface.js +7 -0
- package/dist/starknet/chain/modules/StarknetFees.d.ts +15 -19
- package/dist/starknet/chain/modules/StarknetFees.js +23 -29
- package/dist/starknet/chain/modules/StarknetTransactions.d.ts +32 -6
- package/dist/starknet/chain/modules/StarknetTransactions.js +47 -17
- package/dist/starknet/contract/StarknetContractBase.d.ts +12 -3
- package/dist/starknet/contract/StarknetContractBase.js +2 -2
- package/dist/starknet/contract/modules/StarknetContractEvents.js +1 -1
- package/dist/starknet/events/StarknetChainEvents.d.ts +3 -0
- package/dist/starknet/events/StarknetChainEvents.js +3 -0
- package/dist/starknet/events/StarknetChainEventsBrowser.d.ts +45 -7
- package/dist/starknet/events/StarknetChainEventsBrowser.js +20 -9
- package/dist/starknet/spv_swap/StarknetSpvVaultContract.js +4 -4
- package/dist/starknet/swaps/StarknetSwapContract.js +5 -5
- package/dist/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.js +1 -1
- package/dist/starknet/swaps/modules/StarknetSwapClaim.js +2 -2
- package/dist/starknet/swaps/modules/StarknetSwapRefund.js +1 -1
- package/dist/starknet/wallet/StarknetBrowserSigner.d.ts +9 -1
- package/dist/starknet/wallet/StarknetBrowserSigner.js +31 -1
- package/dist/starknet/wallet/StarknetSigner.d.ts +44 -3
- package/dist/starknet/wallet/StarknetSigner.js +52 -2
- package/dist/utils/Utils.d.ts +1 -1
- package/dist/utils/Utils.js +2 -2
- package/node/index.d.ts +1 -0
- package/node/index.js +3 -0
- package/package.json +5 -4
- package/src/index.ts +76 -2
- package/src/node/index.ts +10 -0
- package/src/starknet/StarknetInitializer.ts +40 -1
- package/src/starknet/btcrelay/StarknetBtcRelay.ts +19 -16
- package/src/starknet/btcrelay/headers/StarknetBtcHeader.ts +2 -0
- package/src/starknet/btcrelay/headers/StarknetBtcStoredHeader.ts +3 -1
- package/src/starknet/chain/StarknetAction.ts +2 -2
- package/src/starknet/chain/StarknetChainInterface.ts +29 -1
- package/src/starknet/chain/modules/StarknetFees.ts +23 -27
- package/src/starknet/chain/modules/StarknetTransactions.ts +59 -18
- package/src/starknet/contract/StarknetContractBase.ts +14 -5
- package/src/starknet/contract/modules/StarknetContractEvents.ts +1 -1
- package/src/starknet/events/StarknetChainEvents.ts +3 -0
- package/src/starknet/events/StarknetChainEventsBrowser.ts +51 -10
- package/src/starknet/spv_swap/StarknetSpvVaultContract.ts +4 -4
- package/src/starknet/swaps/StarknetSwapContract.ts +5 -5
- package/src/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.ts +1 -1
- package/src/starknet/swaps/modules/StarknetSwapClaim.ts +3 -3
- package/src/starknet/swaps/modules/StarknetSwapRefund.ts +2 -2
- package/src/starknet/wallet/StarknetBrowserSigner.ts +39 -2
- package/src/starknet/wallet/StarknetSigner.ts +62 -3
- package/src/utils/Utils.ts +3 -3
|
@@ -25,31 +25,6 @@ export type StarknetGas = {
|
|
|
25
25
|
l1DataGas: number
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
/**
|
|
29
|
-
* Multiplies all the gas parameters by a specific scalar
|
|
30
|
-
*
|
|
31
|
-
* @param gas
|
|
32
|
-
* @param scalar
|
|
33
|
-
*
|
|
34
|
-
* @category Chain Interface
|
|
35
|
-
*/
|
|
36
|
-
export function starknetGasMul(gas: StarknetGas, scalar: number): StarknetGas {
|
|
37
|
-
return {l1Gas: gas.l1Gas * scalar, l2Gas: gas.l2Gas * scalar, l1DataGas: gas.l1DataGas * scalar};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Sums up all the gas parameters
|
|
42
|
-
*
|
|
43
|
-
* @param a
|
|
44
|
-
* @param b
|
|
45
|
-
*
|
|
46
|
-
* @category Chain Interface
|
|
47
|
-
*/
|
|
48
|
-
export function starknetGasAdd(a: StarknetGas, b?: StarknetGas): StarknetGas {
|
|
49
|
-
if(b==null) return a;
|
|
50
|
-
return {l1Gas: a.l1Gas + b.l1Gas, l2Gas: a.l2Gas + b.l2Gas, l1DataGas: a.l1DataGas + b.l1DataGas};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
28
|
/**
|
|
54
29
|
* A module for starknet fee estimation
|
|
55
30
|
*
|
|
@@ -57,6 +32,27 @@ export function starknetGasAdd(a: StarknetGas, b?: StarknetGas): StarknetGas {
|
|
|
57
32
|
*/
|
|
58
33
|
export class StarknetFees {
|
|
59
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Multiplies all the gas parameters by a specific scalar
|
|
37
|
+
*
|
|
38
|
+
* @param gas
|
|
39
|
+
* @param scalar
|
|
40
|
+
*/
|
|
41
|
+
public static starknetGasMul(gas: StarknetGas, scalar: number): StarknetGas {
|
|
42
|
+
return {l1Gas: gas.l1Gas * scalar, l2Gas: gas.l2Gas * scalar, l1DataGas: gas.l1DataGas * scalar};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Sums up all the gas parameters
|
|
47
|
+
*
|
|
48
|
+
* @param a
|
|
49
|
+
* @param b
|
|
50
|
+
*/
|
|
51
|
+
public static starknetGasAdd(a: StarknetGas, b?: StarknetGas): StarknetGas {
|
|
52
|
+
if(b==null) return a;
|
|
53
|
+
return {l1Gas: a.l1Gas + b.l1Gas, l2Gas: a.l2Gas + b.l2Gas, l1DataGas: a.l1DataGas + b.l1DataGas};
|
|
54
|
+
}
|
|
55
|
+
|
|
60
56
|
private readonly logger = getLogger("StarknetFees: ");
|
|
61
57
|
|
|
62
58
|
private readonly feeDA: "L1" | "L2";
|
|
@@ -74,7 +70,7 @@ export class StarknetFees {
|
|
|
74
70
|
* Constructs a new Starknet fee module
|
|
75
71
|
*
|
|
76
72
|
* @param provider A starknet.js provider to use for fee estimation
|
|
77
|
-
* @param maxFeeRate Fee rate limits in base units
|
|
73
|
+
* @param maxFeeRate Fee rate limits in base units, defaults to L1: 20 PFri, L2: 4 PFri, L1 data: 10 PFri
|
|
78
74
|
* @param feeMultiplier A multiplier to use for the returned fee rates
|
|
79
75
|
* @param da Data-availability mode - currently just L1
|
|
80
76
|
*/
|
|
@@ -82,7 +78,7 @@ export class StarknetFees {
|
|
|
82
78
|
provider: Provider,
|
|
83
79
|
maxFeeRate: StarknetFeeRate = {l1GasCost: 20_000_000_000_000_000n, l2GasCost: 4_000_000_000_000_000n, l1DataGasCost: 10_000_000_000_000_000n},
|
|
84
80
|
feeMultiplier: number = 1.25,
|
|
85
|
-
da
|
|
81
|
+
da: {fee?: "L1" | "L2", nonce?: "L1" | "L2"} = {fee: "L1", nonce: "L1"}
|
|
86
82
|
) {
|
|
87
83
|
this.provider = provider;
|
|
88
84
|
this.maxFeeRate = maxFeeRate;
|
|
@@ -13,10 +13,11 @@ import {
|
|
|
13
13
|
CallData,
|
|
14
14
|
Calldata,
|
|
15
15
|
ResourceBounds,
|
|
16
|
-
ResourceBoundsBN
|
|
16
|
+
ResourceBoundsBN, RawArgs
|
|
17
17
|
} from "starknet";
|
|
18
18
|
import {StarknetSigner} from "../../wallet/StarknetSigner";
|
|
19
19
|
import {
|
|
20
|
+
calculateHash,
|
|
20
21
|
deserializeResourceBounds,
|
|
21
22
|
deserializeSignature,
|
|
22
23
|
NoBigInt,
|
|
@@ -32,12 +33,22 @@ export type StarknetTxBase = {
|
|
|
32
33
|
txId?: string
|
|
33
34
|
};
|
|
34
35
|
|
|
36
|
+
/**
|
|
37
|
+
* "INVOKE" type of transaction, used to call smart contracts on Starknet
|
|
38
|
+
*
|
|
39
|
+
* @category Chain Interface
|
|
40
|
+
*/
|
|
35
41
|
export type StarknetTxInvoke = StarknetTxBase & {
|
|
36
42
|
type: "INVOKE",
|
|
37
43
|
tx: Array<Call>,
|
|
38
44
|
signed?: Invocation
|
|
39
45
|
};
|
|
40
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Type-guard for the "INVOKE" type of transaction, used to call smart contracts on Starknet
|
|
49
|
+
*
|
|
50
|
+
* @category Chain Interface
|
|
51
|
+
*/
|
|
41
52
|
export function isStarknetTxInvoke(obj: any): obj is StarknetTxInvoke {
|
|
42
53
|
return typeof(obj)==="object" &&
|
|
43
54
|
typeof(obj.details)==="object" &&
|
|
@@ -47,12 +58,24 @@ export function isStarknetTxInvoke(obj: any): obj is StarknetTxInvoke {
|
|
|
47
58
|
(obj.signed==null || typeof(obj.signed)==="object");
|
|
48
59
|
}
|
|
49
60
|
|
|
61
|
+
/**
|
|
62
|
+
* "DEPLOY_ACCOUNT" type of transaction, used as a first transaction that the account does to deploy its smart
|
|
63
|
+
* account contract on the Starknet
|
|
64
|
+
*
|
|
65
|
+
* @category Chain Interface
|
|
66
|
+
*/
|
|
50
67
|
export type StarknetTxDeployAccount = StarknetTxBase & {
|
|
51
68
|
type: "DEPLOY_ACCOUNT",
|
|
52
69
|
tx: DeployAccountContractPayload,
|
|
53
70
|
signed?: DeployAccountContractTransaction
|
|
54
71
|
};
|
|
55
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Type-guard for the "DEPLOY_ACCOUNT" type of transaction, used as a first transaction that the account does
|
|
75
|
+
* to deploy its smart account contract on the Starknet
|
|
76
|
+
*
|
|
77
|
+
* @category Chain Interface
|
|
78
|
+
*/
|
|
56
79
|
export function isStarknetTxDeployAccount(obj: any): obj is StarknetTxDeployAccount {
|
|
57
80
|
return typeof(obj)==="object" &&
|
|
58
81
|
typeof(obj.details)==="object" &&
|
|
@@ -63,16 +86,18 @@ export function isStarknetTxDeployAccount(obj: any): obj is StarknetTxDeployAcco
|
|
|
63
86
|
}
|
|
64
87
|
|
|
65
88
|
/**
|
|
66
|
-
*
|
|
89
|
+
* Represents a Starknet transactions, which can either be an "INVOKE" or "DEPLOY_ACCOUNT" type, use the
|
|
90
|
+
* {@link isStarknetTxInvoke} & {@link isStarknetTxDeployAccount} to narrow down the type.
|
|
67
91
|
*
|
|
68
92
|
* @category Chain Interface
|
|
69
93
|
*/
|
|
70
94
|
export type StarknetTx = StarknetTxInvoke | StarknetTxDeployAccount;
|
|
71
95
|
|
|
72
96
|
/**
|
|
73
|
-
*
|
|
97
|
+
* Represents a signed Starknet transactions, which can either be an "INVOKE" or "DEPLOY_ACCOUNT" type, use the
|
|
98
|
+
* {@link isStarknetTxInvoke} & {@link isStarknetTxDeployAccount} to narrow down the type.
|
|
74
99
|
*
|
|
75
|
-
* @
|
|
100
|
+
* @remark For Starknet this is just an alias for {@link StarknetTx}
|
|
76
101
|
*
|
|
77
102
|
* @category Chain Interface
|
|
78
103
|
*/
|
|
@@ -280,15 +305,19 @@ export class StarknetTransactions extends StarknetModule {
|
|
|
280
305
|
}
|
|
281
306
|
|
|
282
307
|
/**
|
|
283
|
-
* Prepares starknet transactions, checks if the account is deployed, assigns nonces if needed
|
|
308
|
+
* Prepares starknet transactions, checks if the account is deployed, assigns nonces if needed
|
|
309
|
+
* & calls beforeTxSigned callback (only if signer is passed!)
|
|
284
310
|
*
|
|
285
311
|
* @param signer
|
|
286
312
|
* @param txs
|
|
287
|
-
* @private
|
|
288
313
|
*/
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
const
|
|
314
|
+
public async prepareTransactions(txs: (StarknetTx & {addedInPrepare?: boolean})[], signer?: StarknetSigner): Promise<void> {
|
|
315
|
+
if(txs.length===0) return;
|
|
316
|
+
const signerAddress = signer?.getAddress() ?? txs[0].details.walletAddress;
|
|
317
|
+
if(signerAddress==null) throw new Error("Cannot get tx sender address!");
|
|
318
|
+
|
|
319
|
+
let nonce: bigint = await this.getNonce(signerAddress);
|
|
320
|
+
const latestPendingNonce = this.latestPendingNonces[toHex(signerAddress)];
|
|
292
321
|
if(latestPendingNonce!=null && latestPendingNonce > nonce) {
|
|
293
322
|
this.logger.debug("prepareTransactions(): Using 'pending' nonce from local cache!");
|
|
294
323
|
nonce = latestPendingNonce;
|
|
@@ -296,15 +325,25 @@ export class StarknetTransactions extends StarknetModule {
|
|
|
296
325
|
|
|
297
326
|
//Add deploy account tx
|
|
298
327
|
if(nonce===0n) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
328
|
+
if(signer!=null) {
|
|
329
|
+
const deployPayload = await signer.getDeployPayload();
|
|
330
|
+
if(deployPayload!=null) {
|
|
331
|
+
const tx: (StarknetTx & {addedInPrepare?: boolean}) = await this.root.Accounts.getAccountDeployTransaction(deployPayload);
|
|
332
|
+
tx.addedInPrepare = true;
|
|
333
|
+
txs.unshift(tx);
|
|
334
|
+
}
|
|
335
|
+
} else {
|
|
336
|
+
// Use a 0x0 class hash to indicate that deployment is needed by external signer
|
|
337
|
+
const tx: (StarknetTx & {addedInPrepare?: boolean}) = await this.root.Accounts.getAccountDeployTransaction({
|
|
338
|
+
classHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
339
|
+
contractAddress: signerAddress
|
|
340
|
+
});
|
|
302
341
|
tx.addedInPrepare = true;
|
|
303
342
|
txs.unshift(tx);
|
|
304
343
|
}
|
|
305
344
|
}
|
|
306
345
|
|
|
307
|
-
if(!signer.isManagingNoncesInternally) {
|
|
346
|
+
if(signer==null || !signer.isManagingNoncesInternally) {
|
|
308
347
|
if(nonce===0n) {
|
|
309
348
|
//Just increment the nonce by one and hope the wallet is smart enough to deploy account first
|
|
310
349
|
nonce = 1n;
|
|
@@ -313,7 +352,7 @@ export class StarknetTransactions extends StarknetModule {
|
|
|
313
352
|
for(let i=0;i<txs.length;i++) {
|
|
314
353
|
const tx = txs[i];
|
|
315
354
|
if(tx.details.nonce!=null) nonce = BigInt(tx.details.nonce); //Take the nonce from last tx
|
|
316
|
-
if(nonce==null) nonce = BigInt(await this.root.provider.getNonceForAddress(
|
|
355
|
+
if(nonce==null) nonce = BigInt(await this.root.provider.getNonceForAddress(signerAddress)); //Fetch the nonce
|
|
317
356
|
if(tx.details.nonce==null) tx.details.nonce = nonce;
|
|
318
357
|
|
|
319
358
|
this.logger.debug("prepareTransactions(): transaction prepared ("+(i+1)+"/"+txs.length+"), nonce: "+tx.details.nonce);
|
|
@@ -322,7 +361,7 @@ export class StarknetTransactions extends StarknetModule {
|
|
|
322
361
|
}
|
|
323
362
|
}
|
|
324
363
|
|
|
325
|
-
for(let tx of txs) {
|
|
364
|
+
if(signer!=null) for(let tx of txs) {
|
|
326
365
|
for(let callback of this.cbksBeforeTxSigned) {
|
|
327
366
|
await callback(tx);
|
|
328
367
|
}
|
|
@@ -365,13 +404,14 @@ export class StarknetTransactions extends StarknetModule {
|
|
|
365
404
|
*/
|
|
366
405
|
public async sendAndConfirm(signer: StarknetSigner, _txs: StarknetTx[], waitForConfirmation?: boolean, abortSignal?: AbortSignal, parallel?: boolean, onBeforePublish?: (txId: string, rawTx: string) => Promise<void>): Promise<string[]> {
|
|
367
406
|
const txs: (StarknetTx & {addedInPrepare?: boolean})[] = _txs;
|
|
368
|
-
await this.prepareTransactions(
|
|
407
|
+
await this.prepareTransactions(txs, signer);
|
|
369
408
|
const signedTxs: (StarknetTx & {addedInPrepare?: boolean})[] = [];
|
|
370
409
|
|
|
371
410
|
//Don't separate the signing process from the sending when using browser-based wallet
|
|
372
411
|
if(signer.signTransaction!=null) for(let i=0;i<txs.length;i++) {
|
|
373
412
|
const tx = txs[i];
|
|
374
413
|
const signedTx: (StarknetTx & {addedInPrepare?: boolean}) = await signer.signTransaction(tx);
|
|
414
|
+
calculateHash(signedTx);
|
|
375
415
|
signedTx.addedInPrepare = tx.addedInPrepare;
|
|
376
416
|
signedTxs.push(signedTx);
|
|
377
417
|
this.logger.debug("sendAndConfirm(): transaction signed ("+(i+1)+"/"+txs.length+"): "+signedTx.txId);
|
|
@@ -462,8 +502,9 @@ export class StarknetTransactions extends StarknetModule {
|
|
|
462
502
|
signedTxs: SignedStarknetTx[], waitForConfirmation?: boolean, abortSignal?: AbortSignal,
|
|
463
503
|
parallel?: boolean, onBeforePublish?: (txId: string, rawTx: string) => Promise<void>
|
|
464
504
|
): Promise<string[]> {
|
|
465
|
-
signedTxs.forEach(
|
|
466
|
-
if(
|
|
505
|
+
signedTxs.forEach(tx => {
|
|
506
|
+
if(tx.signed==null) throw new Error("Transactions have to be signed!");
|
|
507
|
+
calculateHash(tx);
|
|
467
508
|
});
|
|
468
509
|
|
|
469
510
|
this.logger.debug("sendSignedAndConfirm(): sending transactions, count: "+signedTxs.length+
|
|
@@ -10,9 +10,18 @@ export class StarknetContractBase<T extends Abi> {
|
|
|
10
10
|
|
|
11
11
|
readonly contract: TypedContractV2<T>;
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
/**
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
readonly _Events: StarknetContractEvents<T>;
|
|
17
|
+
/**
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
protected readonly Chain: StarknetChainInterface;
|
|
21
|
+
/**
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
readonly _contractDeploymentHeight?: number;
|
|
16
25
|
|
|
17
26
|
constructor(
|
|
18
27
|
chainInterface: StarknetChainInterface,
|
|
@@ -26,8 +35,8 @@ export class StarknetContractBase<T extends Abi> {
|
|
|
26
35
|
address: contractAddress,
|
|
27
36
|
providerOrAccount: chainInterface.provider
|
|
28
37
|
}).typedv2(contractAbi);
|
|
29
|
-
this.
|
|
30
|
-
this.
|
|
38
|
+
this._Events = new StarknetContractEvents(chainInterface, this, contractAbi);
|
|
39
|
+
this._contractDeploymentHeight = contractDeploymentHeight;
|
|
31
40
|
}
|
|
32
41
|
|
|
33
42
|
}
|
|
@@ -148,7 +148,7 @@ export class StarknetContractEvents<TAbi extends Abi> extends StarknetEvents {
|
|
|
148
148
|
if(result!=null) return result;
|
|
149
149
|
}
|
|
150
150
|
return null;
|
|
151
|
-
}, Math.max(startHeight ?? 0, this.contract.
|
|
151
|
+
}, Math.max(startHeight ?? 0, this.contract._contractDeploymentHeight ?? 0), abortSignal);
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
}
|
|
@@ -60,6 +60,9 @@ export class StarknetChainEvents extends StarknetChainEventsBrowser {
|
|
|
60
60
|
return fs.writeFile(this.directory+BLOCKHEIGHT_FILENAME, newState.map(value => value.lastTxHash==null ? value.lastBlockNumber.toString(10) : value.lastBlockNumber.toString(10)+";"+value.lastTxHash).join(","));
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
/**
|
|
64
|
+
* @inheritDoc
|
|
65
|
+
*/
|
|
63
66
|
async init(noAutomaticPoll?: boolean): Promise<void> {
|
|
64
67
|
if(noAutomaticPoll) return;
|
|
65
68
|
|
|
@@ -46,7 +46,13 @@ const LOGS_SLIDING_WINDOW = 60;
|
|
|
46
46
|
* @category Events
|
|
47
47
|
*/
|
|
48
48
|
export type StarknetEventListenerState = {
|
|
49
|
+
/**
|
|
50
|
+
* Block number of the last processed event
|
|
51
|
+
*/
|
|
49
52
|
lastBlockNumber: number,
|
|
53
|
+
/**
|
|
54
|
+
* Transaction hash of the last processed event
|
|
55
|
+
*/
|
|
50
56
|
lastTxHash?: string
|
|
51
57
|
};
|
|
52
58
|
|
|
@@ -64,18 +70,51 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData,
|
|
|
64
70
|
} = {};
|
|
65
71
|
private processedEvents: Set<string> = new Set();
|
|
66
72
|
|
|
73
|
+
/**
|
|
74
|
+
* @internal
|
|
75
|
+
*/
|
|
67
76
|
protected readonly Chain: StarknetChainInterface;
|
|
77
|
+
/**
|
|
78
|
+
* @internal
|
|
79
|
+
*/
|
|
68
80
|
protected readonly listeners: EventListener<StarknetSwapData>[] = [];
|
|
81
|
+
/**
|
|
82
|
+
* @internal
|
|
83
|
+
*/
|
|
69
84
|
protected readonly wsChannel?: WebSocketChannel;
|
|
85
|
+
/**
|
|
86
|
+
* @internal
|
|
87
|
+
*/
|
|
70
88
|
protected readonly provider: Provider;
|
|
89
|
+
/**
|
|
90
|
+
* @internal
|
|
91
|
+
*/
|
|
71
92
|
protected readonly starknetSwapContract: StarknetSwapContract;
|
|
93
|
+
/**
|
|
94
|
+
* @internal
|
|
95
|
+
*/
|
|
72
96
|
protected readonly starknetSpvVaultContract: StarknetSpvVaultContract;
|
|
97
|
+
/**
|
|
98
|
+
* @internal
|
|
99
|
+
*/
|
|
73
100
|
protected readonly logger = getLogger("StarknetChainEventsBrowser: ");
|
|
74
101
|
|
|
102
|
+
/**
|
|
103
|
+
* @internal
|
|
104
|
+
*/
|
|
75
105
|
protected escrowContractSubscription?: SubscriptionStarknetEventsEvent;
|
|
106
|
+
/**
|
|
107
|
+
* @internal
|
|
108
|
+
*/
|
|
76
109
|
protected spvVaultContractSubscription?: SubscriptionStarknetEventsEvent;
|
|
77
110
|
|
|
111
|
+
/**
|
|
112
|
+
* @internal
|
|
113
|
+
*/
|
|
78
114
|
protected stopped: boolean = true;
|
|
115
|
+
/**
|
|
116
|
+
* @internal
|
|
117
|
+
*/
|
|
79
118
|
protected pollIntervalSeconds: number;
|
|
80
119
|
|
|
81
120
|
private timeout: any;
|
|
@@ -424,7 +463,7 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData,
|
|
|
424
463
|
return {lastTxHash, lastBlockNumber};
|
|
425
464
|
}
|
|
426
465
|
// this.logger.debug("checkEvents(EscrowManager): Requesting logs: "+logStartHeight+"...pending");
|
|
427
|
-
let events = await this.starknetSwapContract.
|
|
466
|
+
let events = await this.starknetSwapContract._Events.getContractBlockEvents(
|
|
428
467
|
["escrow_manager::events::Initialize", "escrow_manager::events::Claim", "escrow_manager::events::Refund"],
|
|
429
468
|
[],
|
|
430
469
|
lastBlockNumber,
|
|
@@ -454,7 +493,7 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData,
|
|
|
454
493
|
return {lastTxHash, lastBlockNumber};
|
|
455
494
|
}
|
|
456
495
|
|
|
457
|
-
|
|
496
|
+
private async checkEventsSpvVaults(currentBlock: {timestamp: number, block_number: number}, lastTxHash?: string, lastBlockNumber?: number): Promise<StarknetEventListenerState> {
|
|
458
497
|
const currentBlockNumber: number = currentBlock.block_number;
|
|
459
498
|
lastBlockNumber ??= currentBlockNumber;
|
|
460
499
|
if(currentBlockNumber < lastBlockNumber) {
|
|
@@ -462,7 +501,7 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData,
|
|
|
462
501
|
return {lastTxHash, lastBlockNumber};
|
|
463
502
|
}
|
|
464
503
|
// this.logger.debug("checkEvents(SpvVaults): Requesting logs: "+logStartHeight+"...pending");
|
|
465
|
-
let events = await this.starknetSpvVaultContract.
|
|
504
|
+
let events = await this.starknetSpvVaultContract._Events.getContractBlockEvents(
|
|
466
505
|
["spv_swap_vault::events::Opened", "spv_swap_vault::events::Deposited", "spv_swap_vault::events::Closed", "spv_swap_vault::events::Fronted", "spv_swap_vault::events::Claimed"],
|
|
467
506
|
[],
|
|
468
507
|
lastBlockNumber,
|
|
@@ -512,7 +551,7 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData,
|
|
|
512
551
|
/**
|
|
513
552
|
* Sets up event handlers listening for swap events over websocket
|
|
514
553
|
*
|
|
515
|
-
* @
|
|
554
|
+
* @internal
|
|
516
555
|
*/
|
|
517
556
|
protected async setupPoll(
|
|
518
557
|
lastState?: StarknetEventListenerState[],
|
|
@@ -532,6 +571,9 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData,
|
|
|
532
571
|
await func();
|
|
533
572
|
}
|
|
534
573
|
|
|
574
|
+
/**
|
|
575
|
+
* @internal
|
|
576
|
+
*/
|
|
535
577
|
protected wsStarted: boolean = false;
|
|
536
578
|
|
|
537
579
|
/**
|
|
@@ -544,7 +586,7 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData,
|
|
|
544
586
|
try {
|
|
545
587
|
subscription = await this.wsChannel!.subscribeEvents({
|
|
546
588
|
fromAddress: this.starknetSwapContract.contract.address,
|
|
547
|
-
keys: this.starknetSwapContract.
|
|
589
|
+
keys: this.starknetSwapContract._Events.toFilter(
|
|
548
590
|
["escrow_manager::events::Initialize", "escrow_manager::events::Claim", "escrow_manager::events::Refund"],
|
|
549
591
|
[]
|
|
550
592
|
),
|
|
@@ -557,7 +599,7 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData,
|
|
|
557
599
|
} while(subscription==null);
|
|
558
600
|
|
|
559
601
|
subscription.on((event) => {
|
|
560
|
-
const parsedEvents = this.starknetSwapContract.
|
|
602
|
+
const parsedEvents = this.starknetSwapContract._Events.toStarknetAbiEvents<
|
|
561
603
|
"escrow_manager::events::Initialize" | "escrow_manager::events::Claim" | "escrow_manager::events::Refund"
|
|
562
604
|
>([event]);
|
|
563
605
|
this.processEvents(parsedEvents, event.block_number).catch(e => {
|
|
@@ -579,7 +621,7 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData,
|
|
|
579
621
|
try {
|
|
580
622
|
subscription = await this.wsChannel!.subscribeEvents({
|
|
581
623
|
fromAddress: this.starknetSpvVaultContract.contract.address,
|
|
582
|
-
keys: this.starknetSpvVaultContract.
|
|
624
|
+
keys: this.starknetSpvVaultContract._Events.toFilter(
|
|
583
625
|
["spv_swap_vault::events::Opened", "spv_swap_vault::events::Deposited", "spv_swap_vault::events::Closed", "spv_swap_vault::events::Fronted", "spv_swap_vault::events::Claimed"],
|
|
584
626
|
[]
|
|
585
627
|
),
|
|
@@ -592,7 +634,7 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData,
|
|
|
592
634
|
} while(subscription==null);
|
|
593
635
|
|
|
594
636
|
subscription.on((event) => {
|
|
595
|
-
const parsedEvents = this.starknetSpvVaultContract.
|
|
637
|
+
const parsedEvents = this.starknetSpvVaultContract._Events.toStarknetAbiEvents<
|
|
596
638
|
"spv_swap_vault::events::Opened" | "spv_swap_vault::events::Deposited" | "spv_swap_vault::events::Closed" | "spv_swap_vault::events::Fronted" | "spv_swap_vault::events::Claimed"
|
|
597
639
|
>([event]);
|
|
598
640
|
this.processEvents(parsedEvents, event.block_number).catch(e => {
|
|
@@ -605,8 +647,7 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData,
|
|
|
605
647
|
}
|
|
606
648
|
|
|
607
649
|
/**
|
|
608
|
-
*
|
|
609
|
-
* @protected
|
|
650
|
+
* @internal
|
|
610
651
|
*/
|
|
611
652
|
protected async setupWebsocket() {
|
|
612
653
|
if(this.wsChannel==null) throw new Error("Tried to setup websocket subscription on a provider without WS");
|
|
@@ -290,7 +290,7 @@ export class StarknetSpvVaultContract
|
|
|
290
290
|
*/
|
|
291
291
|
async getAllVaults(owner?: string): Promise<StarknetSpvVaultData[]> {
|
|
292
292
|
const openedVaults = new Set<string>();
|
|
293
|
-
await this.
|
|
293
|
+
await this._Events.findInContractEventsForward(
|
|
294
294
|
["spv_swap_vault::events::Opened", "spv_swap_vault::events::Closed"],
|
|
295
295
|
owner==null ? null : [null, null, owner],
|
|
296
296
|
(event) => {
|
|
@@ -444,7 +444,7 @@ export class StarknetSpvVaultContract
|
|
|
444
444
|
}
|
|
445
445
|
});
|
|
446
446
|
|
|
447
|
-
await this.
|
|
447
|
+
await this._Events.findInContractEventsForward(
|
|
448
448
|
events,[lows, highs],
|
|
449
449
|
async (event) => {
|
|
450
450
|
const txId = bigNumberishToBuffer(event.params.btc_tx_hash, 32).reverse().toString("hex");
|
|
@@ -475,7 +475,7 @@ export class StarknetSpvVaultContract
|
|
|
475
475
|
["spv_swap_vault::events::Fronted", "spv_swap_vault::events::Claimed", "spv_swap_vault::events::Closed"];
|
|
476
476
|
const keys = [toHex(txHashU256.low), toHex(txHashU256.high)];
|
|
477
477
|
|
|
478
|
-
await this.
|
|
478
|
+
await this._Events.findInContractEventsForward(
|
|
479
479
|
events, keys,
|
|
480
480
|
async (event) => {
|
|
481
481
|
const eventResult = this.parseWithdrawalEvent(event);
|
|
@@ -496,7 +496,7 @@ export class StarknetSpvVaultContract
|
|
|
496
496
|
const eventTypes: ["spv_swap_vault::events::Fronted", "spv_swap_vault::events::Claimed"] =
|
|
497
497
|
["spv_swap_vault::events::Fronted", "spv_swap_vault::events::Claimed"];
|
|
498
498
|
|
|
499
|
-
await this.
|
|
499
|
+
await this._Events.findInContractEventsForward(
|
|
500
500
|
eventTypes,
|
|
501
501
|
[null, null, null, null, recipient],
|
|
502
502
|
async (_event) => {
|
|
@@ -390,7 +390,7 @@ export class StarknetSwapContract
|
|
|
390
390
|
};
|
|
391
391
|
},
|
|
392
392
|
getClaimTxId: async () => {
|
|
393
|
-
const events = await this.
|
|
393
|
+
const events = await this._Events.getContractBlockEvents(
|
|
394
394
|
["escrow_manager::events::Claim"],
|
|
395
395
|
[null, null, null, "0x"+escrowHash],
|
|
396
396
|
blockHeight, blockHeight
|
|
@@ -399,7 +399,7 @@ export class StarknetSwapContract
|
|
|
399
399
|
return events[0].txHash;
|
|
400
400
|
},
|
|
401
401
|
getClaimResult: async () => {
|
|
402
|
-
const events = await this.
|
|
402
|
+
const events = await this._Events.getContractBlockEvents(
|
|
403
403
|
["escrow_manager::events::Claim"],
|
|
404
404
|
[null, null, null, "0x"+escrowHash],
|
|
405
405
|
blockHeight, blockHeight
|
|
@@ -424,7 +424,7 @@ export class StarknetSwapContract
|
|
|
424
424
|
};
|
|
425
425
|
},
|
|
426
426
|
getRefundTxId: async () => {
|
|
427
|
-
const events = await this.
|
|
427
|
+
const events = await this._Events.getContractBlockEvents(
|
|
428
428
|
["escrow_manager::events::Refund"],
|
|
429
429
|
[null, null, null, "0x"+escrowHash],
|
|
430
430
|
blockHeight, blockHeight
|
|
@@ -604,13 +604,13 @@ export class StarknetSwapContract
|
|
|
604
604
|
};
|
|
605
605
|
|
|
606
606
|
//We have to fetch separately the different directions
|
|
607
|
-
await this.
|
|
607
|
+
await this._Events.findInContractEventsForward(
|
|
608
608
|
["escrow_manager::events::Initialize", "escrow_manager::events::Claim", "escrow_manager::events::Refund"],
|
|
609
609
|
[signer, null],
|
|
610
610
|
processor,
|
|
611
611
|
startBlockheight
|
|
612
612
|
);
|
|
613
|
-
await this.
|
|
613
|
+
await this._Events.findInContractEventsForward(
|
|
614
614
|
["escrow_manager::events::Initialize", "escrow_manager::events::Claim", "escrow_manager::events::Refund"],
|
|
615
615
|
[null, signer],
|
|
616
616
|
processor,
|
|
@@ -61,7 +61,7 @@ export abstract class IBitcoinClaimHandler<C, W extends BitcoinWitnessData> impl
|
|
|
61
61
|
|
|
62
62
|
if(!swapData.isClaimData(commitmentHash)) throw new Error("Invalid commit data");
|
|
63
63
|
|
|
64
|
-
const merkleProof = await btcRelay.
|
|
64
|
+
const merkleProof = await btcRelay._bitcoinRpc.getMerkleProof(tx.txid, tx.blockhash);
|
|
65
65
|
if(merkleProof==null) throw new Error(`Failed to generate merkle proof for tx: ${tx.txid}!`);
|
|
66
66
|
logger.debug("getWitness(): merkle proof computed: ", merkleProof);
|
|
67
67
|
|
|
@@ -6,7 +6,7 @@ import {StarknetAction} from "../../chain/StarknetAction";
|
|
|
6
6
|
import {BigNumberish} from "starknet";
|
|
7
7
|
import {IClaimHandler} from "../handlers/claim/ClaimHandlers";
|
|
8
8
|
import {StarknetTx} from "../../chain/modules/StarknetTransactions";
|
|
9
|
-
import {StarknetFees, StarknetGas
|
|
9
|
+
import {StarknetFees, StarknetGas} from "../../chain/modules/StarknetFees";
|
|
10
10
|
import {StarknetBtcStoredHeader} from "../../btcrelay/headers/StarknetBtcStoredHeader";
|
|
11
11
|
import {BitcoinOutputWitnessData} from "../handlers/claim/btc/BitcoinOutputClaimHandler";
|
|
12
12
|
import {BitcoinWitnessData} from "../handlers/claim/btc/IBitcoinClaimHandler";
|
|
@@ -36,7 +36,7 @@ export class StarknetSwapClaim extends StarknetSwapModule {
|
|
|
36
36
|
): StarknetAction {
|
|
37
37
|
return new StarknetAction(signer, this.root,
|
|
38
38
|
this.swapContract.populateTransaction.claim(swapData.toEscrowStruct(), witness),
|
|
39
|
-
starknetGasAdd(swapData.payOut ? StarknetSwapClaim.GasCosts.CLAIM_PAY_OUT : StarknetSwapClaim.GasCosts.CLAIM, claimHandlerGas)
|
|
39
|
+
StarknetFees.starknetGasAdd(swapData.payOut ? StarknetSwapClaim.GasCosts.CLAIM_PAY_OUT : StarknetSwapClaim.GasCosts.CLAIM, claimHandlerGas)
|
|
40
40
|
);
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -133,7 +133,7 @@ export class StarknetSwapClaim extends StarknetSwapModule {
|
|
|
133
133
|
let gasRequired = swapData.payOut ? StarknetSwapClaim.GasCosts.CLAIM_PAY_OUT : StarknetSwapClaim.GasCosts.CLAIM;
|
|
134
134
|
|
|
135
135
|
const claimHandler: IClaimHandler<any, any> = this.contract.claimHandlersByAddress[toHex(swapData.claimHandler)];
|
|
136
|
-
if(claimHandler!=null) gasRequired = starknetGasAdd(gasRequired, claimHandler.getGas(swapData));
|
|
136
|
+
if(claimHandler!=null) gasRequired = StarknetFees.starknetGasAdd(gasRequired, claimHandler.getGas(swapData));
|
|
137
137
|
|
|
138
138
|
return StarknetFees.getGasFee(gasRequired, feeRate);
|
|
139
139
|
}
|
|
@@ -7,7 +7,7 @@ import {IHandler} from "../handlers/IHandler";
|
|
|
7
7
|
import {BigNumberish} from "starknet";
|
|
8
8
|
import {StarknetTx} from "../../chain/modules/StarknetTransactions";
|
|
9
9
|
import {StarknetSigner} from "../../wallet/StarknetSigner";
|
|
10
|
-
import {StarknetFees, StarknetGas
|
|
10
|
+
import {StarknetFees, StarknetGas} from "../../chain/modules/StarknetFees";
|
|
11
11
|
|
|
12
12
|
const Refund = [
|
|
13
13
|
{ name: 'Swap hash', type: 'felt' },
|
|
@@ -38,7 +38,7 @@ export class StarknetSwapRefund extends StarknetSwapModule {
|
|
|
38
38
|
): StarknetAction {
|
|
39
39
|
return new StarknetAction(signer, this.root,
|
|
40
40
|
this.swapContract.populateTransaction.refund(swapData.toEscrowStruct(), witness),
|
|
41
|
-
starknetGasAdd(swapData.payIn ? StarknetSwapRefund.GasCosts.REFUND_PAY_OUT : StarknetSwapRefund.GasCosts.REFUND, handlerGas)
|
|
41
|
+
StarknetFees.starknetGasAdd(swapData.payIn ? StarknetSwapRefund.GasCosts.REFUND_PAY_OUT : StarknetSwapRefund.GasCosts.REFUND, handlerGas)
|
|
42
42
|
);
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {StarknetSigner} from "./StarknetSigner";
|
|
2
|
-
import {Account} from "starknet";
|
|
2
|
+
import {Account, shortString} from "starknet";
|
|
3
|
+
import {bigNumberishToBuffer, serializeSignature} from "../../utils/Utils";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Browser-based Starknet signer, use with browser based signer accounts, this ensures that
|
|
@@ -9,9 +10,45 @@ import {Account} from "starknet";
|
|
|
9
10
|
*/
|
|
10
11
|
export class StarknetBrowserSigner extends StarknetSigner {
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
private usesECDSADN?: boolean;
|
|
14
|
+
|
|
15
|
+
getReproducibleEntropy?: (appName: string) => Promise<Buffer>;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param account Signer account to request signatures and send transaction through
|
|
19
|
+
* @param usesECDSADN Optional flag indicating whether the signer supports signing using ECDSA-DN (deterministic
|
|
20
|
+
* nonce) algorithm, this allows the wallet to produce reproducible entropy. Only pass `true` here if you are
|
|
21
|
+
* 100% sure that the signer supports this!
|
|
22
|
+
*/
|
|
23
|
+
constructor(account: Account, usesECDSADN?: boolean) {
|
|
13
24
|
super(account, false);
|
|
25
|
+
this.usesECDSADN = usesECDSADN;
|
|
14
26
|
this.signTransaction = undefined;
|
|
27
|
+
if(this.usesECDSADN!==false) {
|
|
28
|
+
this.getReproducibleEntropy = async (appName: string) => {
|
|
29
|
+
if(this.usesECDSADN===false) throw new Error("This wallet doesn't support generating recoverable entropy!");
|
|
30
|
+
|
|
31
|
+
const typedData = StarknetSigner.getReproducibleEntropyMessage(await account.getChainId(), appName);
|
|
32
|
+
|
|
33
|
+
const signature = await account.signMessage(typedData);
|
|
34
|
+
const serializedSignature = serializeSignature(signature)!;
|
|
35
|
+
if(this.usesECDSADN!==true) {
|
|
36
|
+
const secondSignature = serializeSignature(await account.signMessage(typedData))!;
|
|
37
|
+
if(
|
|
38
|
+
serializedSignature.length===secondSignature.length &&
|
|
39
|
+
serializedSignature.every((value, index) => secondSignature[index] === value)
|
|
40
|
+
) {
|
|
41
|
+
this.usesECDSADN = true;
|
|
42
|
+
} else {
|
|
43
|
+
this.usesECDSADN = false;
|
|
44
|
+
this.getReproducibleEntropy = undefined;
|
|
45
|
+
throw new Error("This wallet doesn't support generating recoverable entropy!");
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return Buffer.concat(serializedSignature.map((value) => bigNumberishToBuffer(value, 32)));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
15
52
|
}
|
|
16
53
|
|
|
17
54
|
}
|