@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.
Files changed (63) hide show
  1. package/README.md +74 -0
  2. package/dist/index.d.ts +1 -2
  3. package/dist/index.js +72 -3
  4. package/dist/node/index.d.ts +10 -0
  5. package/dist/node/index.js +15 -0
  6. package/dist/starknet/StarknetInitializer.d.ts +39 -6
  7. package/dist/starknet/StarknetInitializer.js +3 -3
  8. package/dist/starknet/btcrelay/StarknetBtcRelay.d.ts +7 -6
  9. package/dist/starknet/btcrelay/StarknetBtcRelay.js +8 -8
  10. package/dist/starknet/btcrelay/headers/StarknetBtcHeader.d.ts +2 -0
  11. package/dist/starknet/btcrelay/headers/StarknetBtcHeader.js +2 -0
  12. package/dist/starknet/btcrelay/headers/StarknetBtcStoredHeader.d.ts +3 -1
  13. package/dist/starknet/btcrelay/headers/StarknetBtcStoredHeader.js +3 -1
  14. package/dist/starknet/chain/StarknetAction.js +1 -1
  15. package/dist/starknet/chain/StarknetChainInterface.d.ts +25 -0
  16. package/dist/starknet/chain/StarknetChainInterface.js +7 -0
  17. package/dist/starknet/chain/modules/StarknetFees.d.ts +15 -19
  18. package/dist/starknet/chain/modules/StarknetFees.js +23 -29
  19. package/dist/starknet/chain/modules/StarknetTransactions.d.ts +32 -6
  20. package/dist/starknet/chain/modules/StarknetTransactions.js +47 -17
  21. package/dist/starknet/contract/StarknetContractBase.d.ts +12 -3
  22. package/dist/starknet/contract/StarknetContractBase.js +2 -2
  23. package/dist/starknet/contract/modules/StarknetContractEvents.js +1 -1
  24. package/dist/starknet/events/StarknetChainEvents.d.ts +3 -0
  25. package/dist/starknet/events/StarknetChainEvents.js +3 -0
  26. package/dist/starknet/events/StarknetChainEventsBrowser.d.ts +45 -7
  27. package/dist/starknet/events/StarknetChainEventsBrowser.js +20 -9
  28. package/dist/starknet/spv_swap/StarknetSpvVaultContract.js +4 -4
  29. package/dist/starknet/swaps/StarknetSwapContract.js +5 -5
  30. package/dist/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.js +1 -1
  31. package/dist/starknet/swaps/modules/StarknetSwapClaim.js +2 -2
  32. package/dist/starknet/swaps/modules/StarknetSwapRefund.js +1 -1
  33. package/dist/starknet/wallet/StarknetBrowserSigner.d.ts +9 -1
  34. package/dist/starknet/wallet/StarknetBrowserSigner.js +31 -1
  35. package/dist/starknet/wallet/StarknetSigner.d.ts +44 -3
  36. package/dist/starknet/wallet/StarknetSigner.js +52 -2
  37. package/dist/utils/Utils.d.ts +1 -1
  38. package/dist/utils/Utils.js +2 -2
  39. package/node/index.d.ts +1 -0
  40. package/node/index.js +3 -0
  41. package/package.json +5 -4
  42. package/src/index.ts +76 -2
  43. package/src/node/index.ts +10 -0
  44. package/src/starknet/StarknetInitializer.ts +40 -1
  45. package/src/starknet/btcrelay/StarknetBtcRelay.ts +19 -16
  46. package/src/starknet/btcrelay/headers/StarknetBtcHeader.ts +2 -0
  47. package/src/starknet/btcrelay/headers/StarknetBtcStoredHeader.ts +3 -1
  48. package/src/starknet/chain/StarknetAction.ts +2 -2
  49. package/src/starknet/chain/StarknetChainInterface.ts +29 -1
  50. package/src/starknet/chain/modules/StarknetFees.ts +23 -27
  51. package/src/starknet/chain/modules/StarknetTransactions.ts +59 -18
  52. package/src/starknet/contract/StarknetContractBase.ts +14 -5
  53. package/src/starknet/contract/modules/StarknetContractEvents.ts +1 -1
  54. package/src/starknet/events/StarknetChainEvents.ts +3 -0
  55. package/src/starknet/events/StarknetChainEventsBrowser.ts +51 -10
  56. package/src/starknet/spv_swap/StarknetSpvVaultContract.ts +4 -4
  57. package/src/starknet/swaps/StarknetSwapContract.ts +5 -5
  58. package/src/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.ts +1 -1
  59. package/src/starknet/swaps/modules/StarknetSwapClaim.ts +3 -3
  60. package/src/starknet/swaps/modules/StarknetSwapRefund.ts +2 -2
  61. package/src/starknet/wallet/StarknetBrowserSigner.ts +39 -2
  62. package/src/starknet/wallet/StarknetSigner.ts +62 -3
  63. 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?: {fee?: "L1" | "L2", nonce?: "L1" | "L2"}
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
- * Unsigned starknet transaction, either an invoke transaction calling contracts or account deploy transaction
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
- * Signed starknet transaction, either an invoke transaction calling contracts or account deploy transaction.
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
- * @remarks Uses the same type as the unsinged tx for Starknet!
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 & calls beforeTxSigned callback
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
- private async prepareTransactions(signer: StarknetSigner, txs: (StarknetTx & {addedInPrepare?: boolean})[]): Promise<void> {
290
- let nonce: bigint = await this.getNonce(signer.getAddress());
291
- const latestPendingNonce = this.latestPendingNonces[toHex(signer.getAddress())];
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
- const deployPayload = await signer.getDeployPayload();
300
- if(deployPayload!=null) {
301
- const tx: (StarknetTx & {addedInPrepare?: boolean}) = await this.root.Accounts.getAccountDeployTransaction(deployPayload);
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(signer.getAddress())); //Fetch the nonce
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(signer, txs);
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(val => {
466
- if(val.signed==null) throw new Error("Transactions have to be signed!");
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
- readonly Events: StarknetContractEvents<T>;
14
- readonly Chain: StarknetChainInterface;
15
- readonly contractDeploymentHeight?: number;
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.Events = new StarknetContractEvents(chainInterface, this, contractAbi);
30
- this.contractDeploymentHeight = contractDeploymentHeight;
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.contractDeploymentHeight ?? 0), abortSignal);
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.Events.getContractBlockEvents(
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
- protected async checkEventsSpvVaults(currentBlock: {timestamp: number, block_number: number}, lastTxHash?: string, lastBlockNumber?: number): Promise<StarknetEventListenerState> {
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.Events.getContractBlockEvents(
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
- * @protected
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.Events.toFilter(
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.Events.toStarknetAbiEvents<
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.Events.toFilter(
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.Events.toStarknetAbiEvents<
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.Events.findInContractEventsForward(
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.Events.findInContractEventsForward(
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.Events.findInContractEventsForward(
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.Events.findInContractEventsForward(
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.Events.getContractBlockEvents(
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.Events.getContractBlockEvents(
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.Events.getContractBlockEvents(
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.Events.findInContractEventsForward(
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.Events.findInContractEventsForward(
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.bitcoinRpc.getMerkleProof(tx.txid, tx.blockhash);
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, starknetGasAdd} from "../../chain/modules/StarknetFees";
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, starknetGasAdd} from "../../chain/modules/StarknetFees";
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
- constructor(account: Account) {
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
  }