@atomiqlabs/chain-starknet 1.0.8 → 2.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +13 -9
- package/dist/index.js +13 -9
- package/dist/starknet/StarknetChainType.d.ts +6 -2
- package/dist/starknet/StarknetInitializer.d.ts +3 -2
- package/dist/starknet/StarknetInitializer.js +17 -6
- package/dist/starknet/btcrelay/StarknetBtcRelay.d.ts +28 -7
- package/dist/starknet/btcrelay/StarknetBtcRelay.js +75 -20
- package/dist/starknet/{base → chain}/StarknetAction.d.ts +2 -2
- package/dist/starknet/chain/StarknetChainInterface.d.ts +52 -0
- package/dist/starknet/chain/StarknetChainInterface.js +91 -0
- package/dist/starknet/{base → chain}/StarknetModule.d.ts +3 -3
- package/dist/starknet/{base → chain}/modules/StarknetAddresses.d.ts +1 -1
- package/dist/starknet/{base → chain}/modules/StarknetAddresses.js +1 -1
- package/dist/starknet/{base → chain}/modules/StarknetSignatures.d.ts +2 -2
- package/dist/starknet/{base → chain}/modules/StarknetTokens.js +2 -1
- package/dist/starknet/{base → chain}/modules/StarknetTransactions.d.ts +7 -1
- package/dist/starknet/{base → chain}/modules/StarknetTransactions.js +45 -16
- package/dist/starknet/contract/StarknetContractBase.d.ts +5 -5
- package/dist/starknet/contract/StarknetContractBase.js +5 -7
- package/dist/starknet/contract/StarknetContractModule.d.ts +8 -0
- package/dist/starknet/contract/StarknetContractModule.js +11 -0
- package/dist/starknet/contract/modules/StarknetContractEvents.d.ts +15 -4
- package/dist/starknet/contract/modules/StarknetContractEvents.js +26 -6
- package/dist/starknet/events/StarknetChainEvents.d.ts +3 -1
- package/dist/starknet/events/StarknetChainEvents.js +9 -9
- package/dist/starknet/events/StarknetChainEventsBrowser.d.ts +24 -6
- package/dist/starknet/events/StarknetChainEventsBrowser.js +116 -28
- package/dist/starknet/provider/RpcProviderWithRetries.d.ts +21 -0
- package/dist/starknet/provider/RpcProviderWithRetries.js +32 -0
- package/dist/starknet/spv_swap/SpvVaultContractAbi.d.ts +488 -0
- package/dist/starknet/spv_swap/SpvVaultContractAbi.js +656 -0
- package/dist/starknet/spv_swap/StarknetSpvVaultContract.d.ts +65 -0
- package/dist/starknet/spv_swap/StarknetSpvVaultContract.js +372 -0
- package/dist/starknet/spv_swap/StarknetSpvVaultData.d.ts +49 -0
- package/dist/starknet/spv_swap/StarknetSpvVaultData.js +144 -0
- package/dist/starknet/spv_swap/StarknetSpvWithdrawalData.d.ts +24 -0
- package/dist/starknet/spv_swap/StarknetSpvWithdrawalData.js +61 -0
- package/dist/starknet/swaps/StarknetSwapContract.d.ts +4 -22
- package/dist/starknet/swaps/StarknetSwapContract.js +23 -80
- package/dist/starknet/swaps/StarknetSwapModule.d.ts +6 -5
- package/dist/starknet/swaps/StarknetSwapModule.js +5 -6
- package/dist/starknet/swaps/handlers/IHandler.d.ts +2 -2
- package/dist/starknet/swaps/handlers/claim/ClaimHandlers.d.ts +1 -1
- package/dist/starknet/swaps/handlers/claim/HashlockClaimHandler.d.ts +2 -2
- package/dist/starknet/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.d.ts +2 -2
- package/dist/starknet/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.d.ts +2 -2
- package/dist/starknet/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.d.ts +2 -2
- package/dist/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.d.ts +2 -21
- package/dist/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.js +7 -41
- package/dist/starknet/swaps/handlers/refund/TimelockRefundHandler.d.ts +2 -2
- package/dist/starknet/swaps/modules/StarknetLpVault.d.ts +1 -1
- package/dist/starknet/swaps/modules/StarknetLpVault.js +9 -9
- package/dist/starknet/swaps/modules/StarknetSwapClaim.d.ts +1 -1
- package/dist/starknet/swaps/modules/StarknetSwapClaim.js +8 -8
- package/dist/starknet/swaps/modules/StarknetSwapInit.d.ts +1 -1
- package/dist/starknet/swaps/modules/StarknetSwapInit.js +9 -9
- package/dist/starknet/swaps/modules/StarknetSwapRefund.d.ts +1 -3
- package/dist/starknet/swaps/modules/StarknetSwapRefund.js +8 -11
- package/dist/starknet/wallet/StarknetSigner.js +1 -1
- package/dist/utils/Utils.d.ts +2 -2
- package/dist/utils/Utils.js +3 -1
- package/package.json +2 -2
- package/src/index.ts +15 -9
- package/src/starknet/StarknetChainType.ts +10 -2
- package/src/starknet/StarknetInitializer.ts +23 -7
- package/src/starknet/btcrelay/StarknetBtcRelay.ts +104 -30
- package/src/starknet/{base → chain}/StarknetAction.ts +3 -3
- package/src/starknet/chain/StarknetChainInterface.ts +149 -0
- package/src/starknet/{base → chain}/StarknetModule.ts +3 -3
- package/src/starknet/{base → chain}/modules/StarknetAddresses.ts +1 -1
- package/src/starknet/{base → chain}/modules/StarknetSignatures.ts +2 -2
- package/src/starknet/{base → chain}/modules/StarknetTokens.ts +2 -1
- package/src/starknet/{base → chain}/modules/StarknetTransactions.ts +43 -18
- package/src/starknet/contract/StarknetContractBase.ts +9 -12
- package/src/starknet/contract/StarknetContractModule.ts +16 -0
- package/src/starknet/contract/modules/StarknetContractEvents.ts +33 -7
- package/src/starknet/events/StarknetChainEvents.ts +15 -11
- package/src/starknet/events/StarknetChainEventsBrowser.ts +168 -41
- package/src/starknet/provider/RpcProviderWithRetries.ts +43 -0
- package/src/starknet/spv_swap/SpvVaultContractAbi.ts +656 -0
- package/src/starknet/spv_swap/StarknetSpvVaultContract.ts +475 -0
- package/src/starknet/spv_swap/StarknetSpvVaultData.ts +194 -0
- package/src/starknet/spv_swap/StarknetSpvWithdrawalData.ts +68 -0
- package/src/starknet/swaps/StarknetSwapContract.ts +28 -116
- package/src/starknet/swaps/StarknetSwapModule.ts +8 -8
- package/src/starknet/swaps/handlers/IHandler.ts +2 -2
- package/src/starknet/swaps/handlers/claim/ClaimHandlers.ts +1 -1
- package/src/starknet/swaps/handlers/claim/HashlockClaimHandler.ts +2 -2
- package/src/starknet/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.ts +2 -2
- package/src/starknet/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.ts +2 -2
- package/src/starknet/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.ts +2 -2
- package/src/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.ts +12 -61
- package/src/starknet/swaps/handlers/refund/TimelockRefundHandler.ts +2 -2
- package/src/starknet/swaps/modules/StarknetLpVault.ts +10 -10
- package/src/starknet/swaps/modules/StarknetSwapClaim.ts +9 -9
- package/src/starknet/swaps/modules/StarknetSwapInit.ts +10 -10
- package/src/starknet/swaps/modules/StarknetSwapRefund.ts +9 -13
- package/src/starknet/wallet/StarknetSigner.ts +1 -1
- package/src/utils/Utils.ts +4 -3
- package/dist/starknet/base/StarknetBase.d.ts +0 -34
- package/dist/starknet/base/StarknetBase.js +0 -29
- package/src/starknet/base/StarknetBase.ts +0 -56
- /package/dist/starknet/{base → chain}/StarknetAction.js +0 -0
- /package/dist/starknet/{base → chain}/StarknetModule.js +0 -0
- /package/dist/starknet/{base → chain}/modules/ERC20Abi.d.ts +0 -0
- /package/dist/starknet/{base → chain}/modules/ERC20Abi.js +0 -0
- /package/dist/starknet/{base → chain}/modules/StarknetAccounts.d.ts +0 -0
- /package/dist/starknet/{base → chain}/modules/StarknetAccounts.js +0 -0
- /package/dist/starknet/{base → chain}/modules/StarknetBlocks.d.ts +0 -0
- /package/dist/starknet/{base → chain}/modules/StarknetBlocks.js +0 -0
- /package/dist/starknet/{base → chain}/modules/StarknetEvents.d.ts +0 -0
- /package/dist/starknet/{base → chain}/modules/StarknetEvents.js +0 -0
- /package/dist/starknet/{base → chain}/modules/StarknetFees.d.ts +0 -0
- /package/dist/starknet/{base → chain}/modules/StarknetFees.js +0 -0
- /package/dist/starknet/{base → chain}/modules/StarknetSignatures.js +0 -0
- /package/dist/starknet/{base → chain}/modules/StarknetTokens.d.ts +0 -0
- /package/src/starknet/{base → chain}/modules/ERC20Abi.ts +0 -0
- /package/src/starknet/{base → chain}/modules/StarknetAccounts.ts +0 -0
- /package/src/starknet/{base → chain}/modules/StarknetBlocks.ts +0 -0
- /package/src/starknet/{base → chain}/modules/StarknetEvents.ts +0 -0
- /package/src/starknet/{base → chain}/modules/StarknetFees.ts +0 -0
|
@@ -1,29 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {StarknetFees} from "../base/modules/StarknetFees";
|
|
1
|
+
import {StarknetChainInterface} from "../chain/StarknetChainInterface";
|
|
2
|
+
import {Contract, TypedContractV2} from "starknet";
|
|
4
3
|
import {Abi} from "abi-wan-kanabi";
|
|
5
4
|
import {StarknetContractEvents} from "./modules/StarknetContractEvents";
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Base class providing program specific utilities
|
|
9
8
|
*/
|
|
10
|
-
export class StarknetContractBase<T extends Abi>
|
|
9
|
+
export class StarknetContractBase<T extends Abi> {
|
|
11
10
|
|
|
12
11
|
contract: TypedContractV2<T>;
|
|
13
12
|
|
|
14
13
|
public readonly Events: StarknetContractEvents<T>;
|
|
14
|
+
public readonly Chain: StarknetChainInterface;
|
|
15
15
|
|
|
16
16
|
constructor(
|
|
17
|
-
|
|
18
|
-
provider: Provider,
|
|
17
|
+
chainInterface: StarknetChainInterface,
|
|
19
18
|
contractAddress: string,
|
|
20
|
-
contractAbi: T
|
|
21
|
-
retryPolicy?: StarknetRetryPolicy,
|
|
22
|
-
solanaFeeEstimator: StarknetFees = new StarknetFees(provider)
|
|
19
|
+
contractAbi: T
|
|
23
20
|
) {
|
|
24
|
-
|
|
25
|
-
this.contract = new Contract(contractAbi, contractAddress, provider).typedv2(contractAbi);
|
|
26
|
-
this.Events = new StarknetContractEvents(this, contractAbi);
|
|
21
|
+
this.Chain = chainInterface;
|
|
22
|
+
this.contract = new Contract(contractAbi, contractAddress, chainInterface.provider).typedv2(contractAbi);
|
|
23
|
+
this.Events = new StarknetContractEvents(chainInterface, this, contractAbi);
|
|
27
24
|
}
|
|
28
25
|
|
|
29
26
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {Abi} from "abi-wan-kanabi";
|
|
2
|
+
import {StarknetContractBase} from "./StarknetContractBase";
|
|
3
|
+
import {StarknetChainInterface} from "../chain/StarknetChainInterface";
|
|
4
|
+
import {StarknetModule} from "../chain/StarknetModule";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
export class StarknetContractModule<TAbi extends Abi> extends StarknetModule {
|
|
8
|
+
|
|
9
|
+
readonly contract: StarknetContractBase<TAbi>;
|
|
10
|
+
|
|
11
|
+
constructor(chainInterface: StarknetChainInterface, contract: StarknetContractBase<TAbi>) {
|
|
12
|
+
super(chainInterface)
|
|
13
|
+
this.contract = contract;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {Abi} from "abi-wan-kanabi";
|
|
2
2
|
import {EventToPrimitiveType, ExtractAbiEventNames} from "abi-wan-kanabi/dist/kanabi";
|
|
3
|
-
import {StarknetEvent, StarknetEvents} from "../../
|
|
3
|
+
import {StarknetEvent, StarknetEvents} from "../../chain/modules/StarknetEvents";
|
|
4
4
|
import {CallData, events, hash} from "starknet";
|
|
5
5
|
import {StarknetContractBase} from "../StarknetContractBase";
|
|
6
6
|
import {toHex} from "../../../utils/Utils";
|
|
7
|
+
import {StarknetChainInterface} from "../../chain/StarknetChainInterface";
|
|
7
8
|
|
|
8
9
|
export type StarknetAbiEvent<TAbi extends Abi, TEventName extends ExtractAbiEventNames<TAbi>> = {
|
|
9
10
|
name: TEventName,
|
|
@@ -17,11 +18,12 @@ export type StarknetAbiEvent<TAbi extends Abi, TEventName extends ExtractAbiEven
|
|
|
17
18
|
|
|
18
19
|
export class StarknetContractEvents<TAbi extends Abi> extends StarknetEvents {
|
|
19
20
|
|
|
20
|
-
readonly
|
|
21
|
+
readonly contract: StarknetContractBase<TAbi>;
|
|
21
22
|
readonly abi: TAbi;
|
|
22
23
|
|
|
23
|
-
constructor(
|
|
24
|
-
super(
|
|
24
|
+
constructor(chainInterface: StarknetChainInterface, contract: StarknetContractBase<TAbi>, abi: TAbi) {
|
|
25
|
+
super(chainInterface);
|
|
26
|
+
this.contract = contract;
|
|
25
27
|
this.abi = abi;
|
|
26
28
|
}
|
|
27
29
|
|
|
@@ -76,12 +78,12 @@ export class StarknetContractEvents<TAbi extends Abi> extends StarknetEvents {
|
|
|
76
78
|
startBlockHeight?: number,
|
|
77
79
|
endBlockHeight: number = startBlockHeight
|
|
78
80
|
): Promise<StarknetAbiEvent<TAbi, T>[]> {
|
|
79
|
-
const blockEvents = await super.getBlockEvents(this.
|
|
81
|
+
const blockEvents = await super.getBlockEvents(this.contract.contract.address, this.toFilter(events, keys), startBlockHeight, endBlockHeight);
|
|
80
82
|
return this.toStarknetAbiEvents(blockEvents);
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
/**
|
|
84
|
-
* Runs a search
|
|
86
|
+
* Runs a search backwards in time, processing the events for a specific topic public key
|
|
85
87
|
*
|
|
86
88
|
* @param events
|
|
87
89
|
* @param keys
|
|
@@ -95,7 +97,31 @@ export class StarknetContractEvents<TAbi extends Abi> extends StarknetEvents {
|
|
|
95
97
|
processor: (event: StarknetAbiEvent<TAbi, TEvent>) => Promise<T>,
|
|
96
98
|
abortSignal?: AbortSignal
|
|
97
99
|
) {
|
|
98
|
-
return this.findInEvents<T>(this.
|
|
100
|
+
return this.findInEvents<T>(this.contract.contract.address, this.toFilter(events, keys), async (events: StarknetEvent[]) => {
|
|
101
|
+
const parsedEvents = this.toStarknetAbiEvents<TEvent>(events);
|
|
102
|
+
for(let event of parsedEvents) {
|
|
103
|
+
const result: T = await processor(event);
|
|
104
|
+
if(result!=null) return result;
|
|
105
|
+
}
|
|
106
|
+
}, abortSignal);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Runs a search forwards in time, processing the events for a specific topic public key
|
|
111
|
+
*
|
|
112
|
+
* @param events
|
|
113
|
+
* @param keys
|
|
114
|
+
* @param processor called for every event, should return a value if the correct event was found, or null
|
|
115
|
+
* if the search should continue
|
|
116
|
+
* @param abortSignal
|
|
117
|
+
*/
|
|
118
|
+
public async findInContractEventsForward<T, TEvent extends ExtractAbiEventNames<TAbi>>(
|
|
119
|
+
events: TEvent[],
|
|
120
|
+
keys: string[],
|
|
121
|
+
processor: (event: StarknetAbiEvent<TAbi, TEvent>) => Promise<T>,
|
|
122
|
+
abortSignal?: AbortSignal
|
|
123
|
+
) {
|
|
124
|
+
return this.findInEventsForward<T>(this.contract.contract.address, this.toFilter(events, keys), async (events: StarknetEvent[]) => {
|
|
99
125
|
const parsedEvents = this.toStarknetAbiEvents<TEvent>(events);
|
|
100
126
|
for(let event of parsedEvents) {
|
|
101
127
|
const result: T = await processor(event);
|
|
@@ -2,6 +2,8 @@ import {StarknetChainEventsBrowser} from "./StarknetChainEventsBrowser";
|
|
|
2
2
|
//@ts-ignore
|
|
3
3
|
import * as fs from "fs/promises";
|
|
4
4
|
import {StarknetSwapContract} from "../swaps/StarknetSwapContract";
|
|
5
|
+
import {StarknetChainInterface} from "../chain/StarknetChainInterface";
|
|
6
|
+
import {StarknetSpvVaultContract} from "../spv_swap/StarknetSpvVaultContract";
|
|
5
7
|
|
|
6
8
|
const BLOCKHEIGHT_FILENAME = "/strk-blockheight.txt";
|
|
7
9
|
|
|
@@ -11,10 +13,12 @@ export class StarknetChainEvents extends StarknetChainEventsBrowser {
|
|
|
11
13
|
|
|
12
14
|
constructor(
|
|
13
15
|
directory: string,
|
|
16
|
+
chainInterface: StarknetChainInterface,
|
|
14
17
|
starknetSwapContract: StarknetSwapContract,
|
|
18
|
+
starknetSpvVaultContract: StarknetSpvVaultContract,
|
|
15
19
|
pollIntervalSeconds?: number
|
|
16
20
|
) {
|
|
17
|
-
super(starknetSwapContract, pollIntervalSeconds);
|
|
21
|
+
super(chainInterface, starknetSwapContract, starknetSpvVaultContract, pollIntervalSeconds);
|
|
18
22
|
this.directory = directory;
|
|
19
23
|
}
|
|
20
24
|
|
|
@@ -23,22 +27,22 @@ export class StarknetChainEvents extends StarknetChainEventsBrowser {
|
|
|
23
27
|
*
|
|
24
28
|
* @private
|
|
25
29
|
*/
|
|
26
|
-
private async getLastEventData(): Promise<{blockNumber: number,
|
|
30
|
+
private async getLastEventData(): Promise<{blockNumber: number, txHashes: string[]}> {
|
|
27
31
|
try {
|
|
28
|
-
const txt = (await fs.readFile(this.directory+BLOCKHEIGHT_FILENAME)).toString();
|
|
32
|
+
const txt: string = (await fs.readFile(this.directory+BLOCKHEIGHT_FILENAME)).toString();
|
|
29
33
|
const arr = txt.split(";");
|
|
30
34
|
if(arr.length<2) return {
|
|
31
35
|
blockNumber: parseInt(arr[0]),
|
|
32
|
-
|
|
36
|
+
txHashes: null
|
|
33
37
|
};
|
|
34
38
|
return {
|
|
35
39
|
blockNumber: parseInt(arr[0]),
|
|
36
|
-
|
|
40
|
+
txHashes: arr.slice(1)
|
|
37
41
|
};
|
|
38
42
|
} catch (e) {
|
|
39
43
|
return {
|
|
40
44
|
blockNumber: null,
|
|
41
|
-
|
|
45
|
+
txHashes: null
|
|
42
46
|
};
|
|
43
47
|
}
|
|
44
48
|
}
|
|
@@ -48,16 +52,16 @@ export class StarknetChainEvents extends StarknetChainEventsBrowser {
|
|
|
48
52
|
*
|
|
49
53
|
* @private
|
|
50
54
|
*/
|
|
51
|
-
private saveLastEventData(blockNumber: number,
|
|
52
|
-
return fs.writeFile(this.directory+BLOCKHEIGHT_FILENAME, blockNumber.toString()+";"+
|
|
55
|
+
private saveLastEventData(blockNumber: number, txHashes: string[]): Promise<void> {
|
|
56
|
+
return fs.writeFile(this.directory+BLOCKHEIGHT_FILENAME, blockNumber.toString()+";"+txHashes.join(";"));
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
async init(): Promise<void> {
|
|
56
|
-
const {blockNumber,
|
|
60
|
+
const {blockNumber, txHashes} = await this.getLastEventData();
|
|
57
61
|
await this.setupPoll(
|
|
58
62
|
blockNumber,
|
|
59
|
-
|
|
60
|
-
(blockNumber: number,
|
|
63
|
+
txHashes,
|
|
64
|
+
(blockNumber: number, txHashes: string[]) => this.saveLastEventData(blockNumber, txHashes)
|
|
61
65
|
);
|
|
62
66
|
}
|
|
63
67
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ChainEvent,
|
|
2
3
|
ChainEvents,
|
|
3
4
|
ChainSwapType,
|
|
4
5
|
ClaimEvent,
|
|
5
6
|
EventListener,
|
|
6
7
|
InitializeEvent,
|
|
7
|
-
RefundEvent,
|
|
8
|
-
SwapEvent
|
|
8
|
+
RefundEvent, SpvVaultClaimEvent, SpvVaultCloseEvent, SpvVaultDepositEvent, SpvVaultFrontEvent, SpvVaultOpenEvent
|
|
9
9
|
} from "@atomiqlabs/base";
|
|
10
10
|
import {StarknetSwapData} from "../swaps/StarknetSwapData";
|
|
11
11
|
import {
|
|
@@ -13,8 +13,7 @@ import {
|
|
|
13
13
|
bytes31SpanToBuffer, findLastIndex,
|
|
14
14
|
getLogger,
|
|
15
15
|
onceAsync,
|
|
16
|
-
parseInitFunctionCalldata,
|
|
17
|
-
timeoutPromise,
|
|
16
|
+
parseInitFunctionCalldata, toBigInt,
|
|
18
17
|
toHex
|
|
19
18
|
} from "../../utils/Utils";
|
|
20
19
|
import {StarknetSwapContract} from "../swaps/StarknetSwapContract";
|
|
@@ -23,6 +22,9 @@ import {StarknetAbiEvent} from "../contract/modules/StarknetContractEvents";
|
|
|
23
22
|
import {EscrowManagerAbiType} from "../swaps/EscrowManagerAbi";
|
|
24
23
|
import {ExtractAbiFunctionNames} from "abi-wan-kanabi/dist/kanabi";
|
|
25
24
|
import {IClaimHandler} from "../swaps/handlers/claim/ClaimHandlers";
|
|
25
|
+
import {StarknetSpvVaultContract} from "../spv_swap/StarknetSpvVaultContract";
|
|
26
|
+
import {StarknetChainInterface} from "../chain/StarknetChainInterface";
|
|
27
|
+
import {SpvVaultContractAbiType} from "../spv_swap/SpvVaultContractAbi";
|
|
26
28
|
|
|
27
29
|
export type StarknetTraceCall = {
|
|
28
30
|
calldata: string[],
|
|
@@ -41,6 +43,7 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
|
|
|
41
43
|
protected readonly listeners: EventListener<StarknetSwapData>[] = [];
|
|
42
44
|
protected readonly provider: Provider;
|
|
43
45
|
protected readonly starknetSwapContract: StarknetSwapContract;
|
|
46
|
+
protected readonly starknetSpvVaultContract: StarknetSpvVaultContract;
|
|
44
47
|
protected eventListeners: number[] = [];
|
|
45
48
|
protected readonly logger = getLogger("StarknetChainEventsBrowser: ");
|
|
46
49
|
|
|
@@ -52,9 +55,15 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
|
|
|
52
55
|
|
|
53
56
|
private timeout: number;
|
|
54
57
|
|
|
55
|
-
constructor(
|
|
56
|
-
|
|
58
|
+
constructor(
|
|
59
|
+
chainInterface: StarknetChainInterface,
|
|
60
|
+
starknetSwapContract: StarknetSwapContract,
|
|
61
|
+
starknetSpvVaultContract: StarknetSpvVaultContract,
|
|
62
|
+
pollIntervalSeconds: number = 5
|
|
63
|
+
) {
|
|
64
|
+
this.provider = chainInterface.provider;
|
|
57
65
|
this.starknetSwapContract = starknetSwapContract;
|
|
66
|
+
this.starknetSpvVaultContract = starknetSpvVaultContract;
|
|
58
67
|
this.pollIntervalSeconds = pollIntervalSeconds;
|
|
59
68
|
}
|
|
60
69
|
|
|
@@ -146,33 +155,108 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
|
|
|
146
155
|
return new ClaimEvent<StarknetSwapData>(escrowHash, witnessResult);
|
|
147
156
|
}
|
|
148
157
|
|
|
158
|
+
protected parseSpvOpenEvent(
|
|
159
|
+
event: StarknetAbiEvent<SpvVaultContractAbiType, "spv_swap_vault::events::Opened">
|
|
160
|
+
): SpvVaultOpenEvent {
|
|
161
|
+
const owner = toHex(event.params.owner);
|
|
162
|
+
const vaultId = toBigInt(event.params.vault_id);
|
|
163
|
+
const btcTxId = bigNumberishToBuffer(event.params.btc_tx_hash, 32).reverse().toString("hex");
|
|
164
|
+
const vout = Number(toBigInt(event.params.vout));
|
|
165
|
+
|
|
166
|
+
this.logger.debug("SpvOpenEvent owner: "+owner+" vaultId: "+vaultId+" utxo: "+btcTxId+":"+vout);
|
|
167
|
+
return new SpvVaultOpenEvent(owner, vaultId, btcTxId, vout);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
protected parseSpvDepositEvent(
|
|
171
|
+
event: StarknetAbiEvent<SpvVaultContractAbiType, "spv_swap_vault::events::Deposited">
|
|
172
|
+
): SpvVaultDepositEvent {
|
|
173
|
+
const owner = toHex(event.params.owner);
|
|
174
|
+
const vaultId = toBigInt(event.params.vault_id);
|
|
175
|
+
const amounts = [toBigInt(event.params.amounts["0"] as BigNumberish), toBigInt(event.params.amounts["1"] as BigNumberish)];
|
|
176
|
+
const depositCount = Number(toBigInt(event.params.deposit_count));
|
|
177
|
+
|
|
178
|
+
this.logger.debug("SpvDepositEvent owner: "+owner+" vaultId: "+vaultId+" depositCount: "+depositCount+" amounts: ", amounts);
|
|
179
|
+
return new SpvVaultDepositEvent(owner, vaultId, amounts, depositCount);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
protected parseSpvFrontEvent(
|
|
183
|
+
event: StarknetAbiEvent<SpvVaultContractAbiType, "spv_swap_vault::events::Fronted">
|
|
184
|
+
): SpvVaultFrontEvent {
|
|
185
|
+
const owner = toHex(event.params.owner);
|
|
186
|
+
const vaultId = toBigInt(event.params.vault_id);
|
|
187
|
+
const btcTxId = bigNumberishToBuffer(event.params.btc_tx_hash, 32).reverse().toString("hex");
|
|
188
|
+
const recipient = toHex(event.params.recipient);
|
|
189
|
+
const executionHash = toHex(event.params.execution_hash);
|
|
190
|
+
const amounts = [toBigInt(event.params.amounts["0"] as BigNumberish), toBigInt(event.params.amounts["1"] as BigNumberish)];
|
|
191
|
+
const frontingAddress = toHex(event.params.caller);
|
|
192
|
+
|
|
193
|
+
this.logger.debug("SpvFrontEvent owner: "+owner+" vaultId: "+vaultId+" btcTxId: "+btcTxId+
|
|
194
|
+
" recipient: "+recipient+" frontedBy: "+frontingAddress+" amounts: ", amounts);
|
|
195
|
+
return new SpvVaultFrontEvent(owner, vaultId, btcTxId, recipient, executionHash, amounts, frontingAddress);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
protected parseSpvClaimEvent(
|
|
199
|
+
event: StarknetAbiEvent<SpvVaultContractAbiType, "spv_swap_vault::events::Claimed">
|
|
200
|
+
): SpvVaultClaimEvent {
|
|
201
|
+
const owner = toHex(event.params.owner);
|
|
202
|
+
const vaultId = toBigInt(event.params.vault_id);
|
|
203
|
+
const btcTxId = bigNumberishToBuffer(event.params.btc_tx_hash, 32).reverse().toString("hex");
|
|
204
|
+
const recipient = toHex(event.params.recipient);
|
|
205
|
+
const executionHash = toHex(event.params.execution_hash);
|
|
206
|
+
const amounts = [toBigInt(event.params.amounts["0"] as BigNumberish), toBigInt(event.params.amounts["1"] as BigNumberish)];
|
|
207
|
+
const caller = toHex(event.params.caller);
|
|
208
|
+
const frontingAddress = toHex(event.params.fronting_address);
|
|
209
|
+
const withdrawCount = Number(toBigInt(event.params.withdraw_count));
|
|
210
|
+
|
|
211
|
+
this.logger.debug("SpvClaimEvent owner: "+owner+" vaultId: "+vaultId+" btcTxId: "+btcTxId+" withdrawCount: "+withdrawCount+
|
|
212
|
+
" recipient: "+recipient+" frontedBy: "+frontingAddress+" claimedBy: "+caller+" amounts: ", amounts);
|
|
213
|
+
return new SpvVaultClaimEvent(owner, vaultId, btcTxId, recipient, executionHash, amounts, caller, frontingAddress, withdrawCount);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
protected parseSpvCloseEvent(
|
|
217
|
+
event: StarknetAbiEvent<SpvVaultContractAbiType, "spv_swap_vault::events::Closed">
|
|
218
|
+
): SpvVaultCloseEvent {
|
|
219
|
+
const owner = toHex(event.params.owner);
|
|
220
|
+
const vaultId = toBigInt(event.params.vault_id);
|
|
221
|
+
const btcTxId = bigNumberishToBuffer(event.params.btc_tx_hash, 32).reverse().toString("hex");
|
|
222
|
+
const error = bigNumberishToBuffer(event.params.error).toString();
|
|
223
|
+
|
|
224
|
+
return new SpvVaultCloseEvent(owner, vaultId, btcTxId, error);
|
|
225
|
+
}
|
|
226
|
+
|
|
149
227
|
/**
|
|
150
228
|
* Processes event as received from the chain, parses it & calls event listeners
|
|
151
229
|
*
|
|
152
230
|
* @param events
|
|
153
231
|
* @param currentBlockNumber
|
|
154
232
|
* @param currentBlockTimestamp
|
|
233
|
+
* @param pendingEventTime
|
|
155
234
|
* @protected
|
|
156
235
|
*/
|
|
157
236
|
protected async processEvents(
|
|
158
|
-
events : StarknetAbiEvent<
|
|
237
|
+
events : (StarknetAbiEvent<
|
|
159
238
|
EscrowManagerAbiType,
|
|
160
239
|
"escrow_manager::events::Initialize" | "escrow_manager::events::Refund" | "escrow_manager::events::Claim"
|
|
161
|
-
>
|
|
240
|
+
> | StarknetAbiEvent<
|
|
241
|
+
SpvVaultContractAbiType,
|
|
242
|
+
"spv_swap_vault::events::Opened" | "spv_swap_vault::events::Deposited" | "spv_swap_vault::events::Fronted" | "spv_swap_vault::events::Claimed" | "spv_swap_vault::events::Closed"
|
|
243
|
+
>)[],
|
|
162
244
|
currentBlockNumber: number,
|
|
163
|
-
currentBlockTimestamp: number
|
|
245
|
+
currentBlockTimestamp: number,
|
|
246
|
+
pendingEventTime: number
|
|
164
247
|
) {
|
|
165
248
|
const blockTimestampsCache: {[blockNumber: string]: number} = {};
|
|
166
249
|
const getBlockTimestamp: (blockNumber: number) => Promise<number> = async (blockNumber: number)=> {
|
|
250
|
+
if(blockNumber===currentBlockNumber) return currentBlockTimestamp;
|
|
167
251
|
const blockNumberString = blockNumber.toString();
|
|
168
252
|
blockTimestampsCache[blockNumberString] ??= (await this.provider.getBlockWithTxHashes(blockNumber)).timestamp;
|
|
169
253
|
return blockTimestampsCache[blockNumberString];
|
|
170
254
|
}
|
|
171
255
|
|
|
172
|
-
const parsedEvents:
|
|
256
|
+
const parsedEvents: ChainEvent<StarknetSwapData>[] = [];
|
|
173
257
|
|
|
174
258
|
for(let event of events) {
|
|
175
|
-
let parsedEvent:
|
|
259
|
+
let parsedEvent: ChainEvent<StarknetSwapData>;
|
|
176
260
|
switch(event.name) {
|
|
177
261
|
case "escrow_manager::events::Claim":
|
|
178
262
|
parsedEvent = this.parseClaimEvent(event as any);
|
|
@@ -183,8 +267,23 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
|
|
|
183
267
|
case "escrow_manager::events::Initialize":
|
|
184
268
|
parsedEvent = this.parseInitializeEvent(event as any);
|
|
185
269
|
break;
|
|
270
|
+
case "spv_swap_vault::events::Opened":
|
|
271
|
+
parsedEvent = this.parseSpvOpenEvent(event as any);
|
|
272
|
+
break;
|
|
273
|
+
case "spv_swap_vault::events::Deposited":
|
|
274
|
+
parsedEvent = this.parseSpvDepositEvent(event as any);
|
|
275
|
+
break;
|
|
276
|
+
case "spv_swap_vault::events::Fronted":
|
|
277
|
+
parsedEvent = this.parseSpvFrontEvent(event as any);
|
|
278
|
+
break;
|
|
279
|
+
case "spv_swap_vault::events::Claimed":
|
|
280
|
+
parsedEvent = this.parseSpvClaimEvent(event as any);
|
|
281
|
+
break;
|
|
282
|
+
case "spv_swap_vault::events::Closed":
|
|
283
|
+
parsedEvent = this.parseSpvCloseEvent(event as any);
|
|
284
|
+
break;
|
|
186
285
|
}
|
|
187
|
-
const timestamp =
|
|
286
|
+
const timestamp = event.blockNumber==null ? pendingEventTime : await getBlockTimestamp(event.blockNumber);
|
|
188
287
|
parsedEvent.meta = {
|
|
189
288
|
blockTime: timestamp,
|
|
190
289
|
txId: event.txHash,
|
|
@@ -198,41 +297,69 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
|
|
|
198
297
|
}
|
|
199
298
|
}
|
|
200
299
|
|
|
201
|
-
protected async
|
|
202
|
-
|
|
203
|
-
|
|
300
|
+
protected async checkEventsEcrowManager(lastTxHash: string, lastBlockNumber?: number, currentBlock?: {timestamp: number, block_number: number}): Promise<string> {
|
|
301
|
+
const currentBlockNumber: number = (currentBlock as any).block_number;
|
|
302
|
+
lastBlockNumber ??= currentBlockNumber;
|
|
303
|
+
const logStartHeight = currentBlockNumber>lastBlockNumber ? lastBlockNumber+1 : lastBlockNumber;
|
|
304
|
+
this.logger.debug("checkEvents(EscrowManager): Requesting logs: "+logStartHeight+"...pending");
|
|
305
|
+
let events = await this.starknetSwapContract.Events.getContractBlockEvents(
|
|
204
306
|
["escrow_manager::events::Initialize", "escrow_manager::events::Claim", "escrow_manager::events::Refund"],
|
|
205
|
-
[]
|
|
307
|
+
[],
|
|
308
|
+
logStartHeight,
|
|
309
|
+
null
|
|
310
|
+
);
|
|
311
|
+
if(lastTxHash!=null) {
|
|
312
|
+
const latestProcessedEventIndex = findLastIndex(events, val => val.txHash===lastTxHash);
|
|
313
|
+
if(latestProcessedEventIndex!==-1) {
|
|
314
|
+
events.splice(0, latestProcessedEventIndex+1);
|
|
315
|
+
this.logger.debug("checkEvents(EscrowManager): Splicing processed events, resulting size: "+events.length);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
if(events.length>0) {
|
|
319
|
+
await this.processEvents(events, currentBlock?.block_number, currentBlock?.timestamp, Math.floor(Date.now()/1000));
|
|
320
|
+
lastTxHash = events[events.length-1].txHash;
|
|
321
|
+
}
|
|
322
|
+
return lastTxHash;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
protected async checkEventsSpvVaults(lastTxHash: string, lastBlockNumber?: number, currentBlock?: {timestamp: number, block_number: number}): Promise<string> {
|
|
326
|
+
const currentBlockNumber: number = (currentBlock as any).block_number;
|
|
327
|
+
lastBlockNumber ??= currentBlockNumber;
|
|
328
|
+
const logStartHeight = currentBlockNumber>lastBlockNumber ? lastBlockNumber+1 : lastBlockNumber;
|
|
329
|
+
this.logger.debug("checkEvents(SpvVaults): Requesting logs: "+logStartHeight+"...pending");
|
|
330
|
+
let events = await this.starknetSpvVaultContract.Events.getContractBlockEvents(
|
|
331
|
+
["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"],
|
|
332
|
+
[],
|
|
333
|
+
logStartHeight,
|
|
334
|
+
null
|
|
206
335
|
);
|
|
207
336
|
if(lastTxHash!=null) {
|
|
208
|
-
const latestProcessedEventIndex = findLastIndex(
|
|
209
|
-
if(latestProcessedEventIndex!==-1)
|
|
337
|
+
const latestProcessedEventIndex = findLastIndex(events, val => val.txHash===lastTxHash);
|
|
338
|
+
if(latestProcessedEventIndex!==-1) {
|
|
339
|
+
events.splice(0, latestProcessedEventIndex+1);
|
|
340
|
+
this.logger.debug("checkEvents(SpvVaults): Splicing processed events, resulting size: "+events.length);
|
|
341
|
+
}
|
|
210
342
|
}
|
|
211
|
-
if(
|
|
212
|
-
await this.processEvents(
|
|
213
|
-
lastTxHash =
|
|
343
|
+
if(events.length>0) {
|
|
344
|
+
await this.processEvents(events, currentBlock?.block_number, currentBlock?.timestamp, Math.floor(Date.now()/1000));
|
|
345
|
+
lastTxHash = events[events.length-1].txHash;
|
|
214
346
|
}
|
|
347
|
+
return lastTxHash;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
protected async checkEvents(lastBlockNumber: number, lastTxHashes: string[]): Promise<{txHashes: string[], blockNumber: number}> {
|
|
351
|
+
lastTxHashes ??= [];
|
|
215
352
|
|
|
216
353
|
const currentBlock = await this.provider.getBlockWithTxHashes("latest");
|
|
217
354
|
const currentBlockNumber: number = (currentBlock as any).block_number;
|
|
355
|
+
|
|
218
356
|
if(lastBlockNumber!=null && currentBlockNumber>lastBlockNumber) {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
[],
|
|
222
|
-
lastBlockNumber+1,
|
|
223
|
-
currentBlockNumber
|
|
224
|
-
);
|
|
225
|
-
if(lastTxHash!=null) {
|
|
226
|
-
const latestProcessedEventIndex = findLastIndex(events, val => val.txHash === lastTxHash);
|
|
227
|
-
if (latestProcessedEventIndex !== -1) events.splice(0, latestProcessedEventIndex + 1);
|
|
228
|
-
}
|
|
229
|
-
if(events.length>0) {
|
|
230
|
-
await this.processEvents(events, currentBlockNumber, currentBlock.timestamp);
|
|
231
|
-
lastTxHash = events[events.length - 1].txHash;
|
|
232
|
-
}
|
|
357
|
+
lastTxHashes[0] = await this.checkEventsEcrowManager(lastTxHashes[0], lastBlockNumber, currentBlock as any);
|
|
358
|
+
lastTxHashes[1] = await this.checkEventsSpvVaults(lastTxHashes[1], lastBlockNumber, currentBlock as any);
|
|
233
359
|
}
|
|
360
|
+
|
|
234
361
|
return {
|
|
235
|
-
|
|
362
|
+
txHashes: lastTxHashes,
|
|
236
363
|
blockNumber: currentBlockNumber
|
|
237
364
|
};
|
|
238
365
|
}
|
|
@@ -244,16 +371,16 @@ export class StarknetChainEventsBrowser implements ChainEvents<StarknetSwapData>
|
|
|
244
371
|
*/
|
|
245
372
|
protected async setupPoll(
|
|
246
373
|
lastBlockNumber?: number,
|
|
247
|
-
|
|
248
|
-
saveLatestProcessedBlockNumber?: (blockNumber: number,
|
|
374
|
+
lastTxHashes?: string[],
|
|
375
|
+
saveLatestProcessedBlockNumber?: (blockNumber: number, lastTxHashes: string[]) => Promise<void>
|
|
249
376
|
) {
|
|
250
377
|
this.stopped = false;
|
|
251
378
|
let func;
|
|
252
379
|
func = async () => {
|
|
253
|
-
await this.checkEvents(lastBlockNumber,
|
|
380
|
+
await this.checkEvents(lastBlockNumber, lastTxHashes).then(({blockNumber, txHashes}) => {
|
|
254
381
|
lastBlockNumber = blockNumber;
|
|
255
|
-
|
|
256
|
-
if(saveLatestProcessedBlockNumber!=null) return saveLatestProcessedBlockNumber(blockNumber,
|
|
382
|
+
lastTxHashes = txHashes;
|
|
383
|
+
if(saveLatestProcessedBlockNumber!=null) return saveLatestProcessedBlockNumber(blockNumber, lastTxHashes);
|
|
257
384
|
}).catch(e => {
|
|
258
385
|
this.logger.error("setupPoll(): Failed to fetch starknet log: ", e);
|
|
259
386
|
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RpcChannel,
|
|
3
|
+
RpcProvider,
|
|
4
|
+
RpcProviderOptions
|
|
5
|
+
} from "starknet";
|
|
6
|
+
import {tryWithRetries} from "../../utils/Utils";
|
|
7
|
+
|
|
8
|
+
export class RpcChannelWithRetries extends RpcChannel {
|
|
9
|
+
|
|
10
|
+
readonly retryPolicy?: {
|
|
11
|
+
maxRetries?: number, delay?: number, exponential?: boolean
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
constructor(options?: RpcProviderOptions, retryPolicy?: {
|
|
15
|
+
maxRetries?: number, delay?: number, exponential?: boolean
|
|
16
|
+
}) {
|
|
17
|
+
super(options);
|
|
18
|
+
this.retryPolicy = retryPolicy;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
protected fetchEndpoint(method: any, params?: any): Promise<any> {
|
|
22
|
+
return tryWithRetries(() => super.fetchEndpoint(method, params), this.retryPolicy, e => {
|
|
23
|
+
if(!e.message.startsWith("RPC: ")) return false;
|
|
24
|
+
const arr = e.message.split("\n");
|
|
25
|
+
const errorCode = parseInt(arr[arr.length-1]);
|
|
26
|
+
if(isNaN(errorCode)) return false;
|
|
27
|
+
if(errorCode < 0) return false; //Not defined error, e.g. Rate limit (-32097)
|
|
28
|
+
return true;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class RpcProviderWithRetries extends RpcProvider {
|
|
35
|
+
|
|
36
|
+
constructor(options?: RpcProviderOptions, retryPolicy?: {
|
|
37
|
+
maxRetries?: number, delay?: number, exponential?: boolean
|
|
38
|
+
}) {
|
|
39
|
+
super(options);
|
|
40
|
+
this.channel = new RpcChannelWithRetries({ ...options, waitMode: false }, retryPolicy);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
}
|