@atomiqlabs/chain-starknet 8.0.13 → 8.1.7
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/starknet/StarknetInitializer.d.ts +3 -0
- package/dist/starknet/StarknetInitializer.js +3 -3
- package/dist/starknet/btcrelay/StarknetBtcRelay.d.ts +1 -1
- package/dist/starknet/btcrelay/StarknetBtcRelay.js +10 -2
- package/dist/starknet/chain/modules/StarknetTransactions.d.ts +7 -0
- package/dist/starknet/chain/modules/StarknetTransactions.js +21 -0
- package/dist/starknet/contract/StarknetContractBase.d.ts +2 -1
- package/dist/starknet/contract/StarknetContractBase.js +2 -1
- package/dist/starknet/contract/modules/StarknetContractEvents.js +1 -1
- package/dist/starknet/events/StarknetChainEventsBrowser.d.ts +0 -12
- package/dist/starknet/events/StarknetChainEventsBrowser.js +2 -61
- package/dist/starknet/spv_swap/StarknetSpvVaultContract.d.ts +8 -2
- package/dist/starknet/spv_swap/StarknetSpvVaultContract.js +45 -8
- package/dist/starknet/swaps/StarknetSwapContract.d.ts +35 -3
- package/dist/starknet/swaps/StarknetSwapContract.js +178 -2
- package/package.json +2 -2
- package/src/starknet/StarknetInitializer.ts +6 -3
- package/src/starknet/btcrelay/StarknetBtcRelay.ts +15 -2
- package/src/starknet/chain/modules/StarknetTransactions.ts +24 -0
- package/src/starknet/contract/StarknetContractBase.ts +4 -1
- package/src/starknet/contract/modules/StarknetContractEvents.ts +1 -1
- package/src/starknet/events/StarknetChainEventsBrowser.ts +2 -64
- package/src/starknet/spv_swap/StarknetSpvVaultContract.ts +68 -10
- package/src/starknet/swaps/StarknetSwapContract.ts +242 -6
|
@@ -10,15 +10,15 @@ import {
|
|
|
10
10
|
TransactionConfirmationOptions
|
|
11
11
|
} from "@atomiqlabs/base";
|
|
12
12
|
import {Buffer} from "buffer";
|
|
13
|
-
import {EscrowManagerAbi} from "./EscrowManagerAbi";
|
|
13
|
+
import {EscrowManagerAbi, EscrowManagerAbiType} from "./EscrowManagerAbi";
|
|
14
14
|
import {StarknetContractBase} from "../contract/StarknetContractBase";
|
|
15
|
-
import {StarknetTx} from "../chain/modules/StarknetTransactions";
|
|
15
|
+
import {StarknetTraceCall, StarknetTx} from "../chain/modules/StarknetTransactions";
|
|
16
16
|
import {StarknetSigner} from "../wallet/StarknetSigner";
|
|
17
|
-
import {BigNumberish, constants, logger} from "starknet";
|
|
17
|
+
import {BigNumberish, constants, hash, logger} from "starknet";
|
|
18
18
|
import {StarknetChainInterface} from "../chain/StarknetChainInterface";
|
|
19
19
|
import {StarknetBtcRelay} from "../btcrelay/StarknetBtcRelay";
|
|
20
20
|
import {StarknetSwapData} from "./StarknetSwapData";
|
|
21
|
-
import {bigNumberishToBuffer, toHex} from "../../utils/Utils";
|
|
21
|
+
import {bigNumberishToBuffer, bytes31SpanToBuffer, toBigInt, toHex} from "../../utils/Utils";
|
|
22
22
|
import {TimelockRefundHandler} from "./handlers/refund/TimelockRefundHandler";
|
|
23
23
|
import {StarknetLpVault} from "./modules/StarknetLpVault";
|
|
24
24
|
import {StarknetPreFetchVerification, StarknetSwapInit} from "./modules/StarknetSwapInit";
|
|
@@ -28,6 +28,8 @@ import {StarknetSwapClaim} from "./modules/StarknetSwapClaim";
|
|
|
28
28
|
import {IHandler} from "./handlers/IHandler";
|
|
29
29
|
import {StarknetBtcStoredHeader} from "../btcrelay/headers/StarknetBtcStoredHeader";
|
|
30
30
|
import {sha256} from "@noble/hashes/sha2";
|
|
31
|
+
import {StarknetAbiEvent} from "../contract/modules/StarknetContractEvents";
|
|
32
|
+
import {ExtractAbiFunctionNames} from "abi-wan-kanabi/dist/kanabi";
|
|
31
33
|
|
|
32
34
|
const ESCROW_STATE_COMMITTED = 1;
|
|
33
35
|
const ESCROW_STATE_CLAIMED = 2;
|
|
@@ -38,6 +40,11 @@ const swapContractAddreses = {
|
|
|
38
40
|
[constants.StarknetChainId.SN_MAIN]: "0x04f278e1f19e495c3b1dd35ef307c4f7510768ed95481958fbae588bd173f79a"
|
|
39
41
|
};
|
|
40
42
|
|
|
43
|
+
const swapContractDeploymentHeights = {
|
|
44
|
+
[constants.StarknetChainId.SN_SEPOLIA]: 1118142,
|
|
45
|
+
[constants.StarknetChainId.SN_MAIN]: 1617247
|
|
46
|
+
};
|
|
47
|
+
|
|
41
48
|
const defaultClaimAddresses = {
|
|
42
49
|
[constants.StarknetChainId.SN_SEPOLIA]: {
|
|
43
50
|
[ChainSwapType.HTLC]: "0x04a57ea54d4637c352aad1bbee046868926a11702216a0aaf7eeec1568be2d7b",
|
|
@@ -127,6 +134,9 @@ export class StarknetSwapContract
|
|
|
127
134
|
|
|
128
135
|
readonly btcRelay: StarknetBtcRelay<any>;
|
|
129
136
|
|
|
137
|
+
protected readonly initFunctionName: ExtractAbiFunctionNames<EscrowManagerAbiType> = "initialize";
|
|
138
|
+
protected readonly initEntryPointSelector = BigInt(hash.starknetKeccak(this.initFunctionName));
|
|
139
|
+
|
|
130
140
|
/**
|
|
131
141
|
* Constructs the swap contract (escrow manager)
|
|
132
142
|
*
|
|
@@ -134,6 +144,7 @@ export class StarknetSwapContract
|
|
|
134
144
|
* @param btcRelay Btc relay light client contract
|
|
135
145
|
* @param contractAddress Optional underlying contract address (default is used otherwise)
|
|
136
146
|
* @param _handlerAddresses Optional handler addresses (defaults are used otherwise)
|
|
147
|
+
* @param contractDeploymentHeight The height at which this contract was deployed (default is used otherwise)
|
|
137
148
|
*/
|
|
138
149
|
constructor(
|
|
139
150
|
chainInterface: StarknetChainInterface,
|
|
@@ -146,9 +157,16 @@ export class StarknetSwapContract
|
|
|
146
157
|
claim?: {
|
|
147
158
|
[type in ChainSwapType]?: string
|
|
148
159
|
}
|
|
149
|
-
}
|
|
160
|
+
},
|
|
161
|
+
contractDeploymentHeight?: number
|
|
150
162
|
) {
|
|
151
|
-
super(
|
|
163
|
+
super(
|
|
164
|
+
chainInterface, contractAddress, EscrowManagerAbi,
|
|
165
|
+
contractDeploymentHeight ??
|
|
166
|
+
(swapContractAddreses[chainInterface.starknetChainId]===contractAddress
|
|
167
|
+
? swapContractDeploymentHeights[chainInterface.starknetChainId]
|
|
168
|
+
: undefined)
|
|
169
|
+
);
|
|
152
170
|
this.Init = new StarknetSwapInit(chainInterface, this);
|
|
153
171
|
this.Refund = new StarknetSwapRefund(chainInterface, this);
|
|
154
172
|
this.Claim = new StarknetSwapClaim(chainInterface, this);
|
|
@@ -446,6 +464,186 @@ export class StarknetSwapContract
|
|
|
446
464
|
return result;
|
|
447
465
|
}
|
|
448
466
|
|
|
467
|
+
/**
|
|
468
|
+
* @inheritDoc
|
|
469
|
+
*/
|
|
470
|
+
async getHistoricalSwaps(signer: string, startBlockheight?: number): Promise<{
|
|
471
|
+
swaps: {
|
|
472
|
+
[escrowHash: string]: {
|
|
473
|
+
init?: {
|
|
474
|
+
data: StarknetSwapData;
|
|
475
|
+
getInitTxId: () => Promise<string>;
|
|
476
|
+
getTxBlock: () => Promise<{ blockTime: number; blockHeight: number }>
|
|
477
|
+
};
|
|
478
|
+
state: SwapCommitState
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
latestBlockheight?: number
|
|
482
|
+
}> {
|
|
483
|
+
const {height: latestBlockheight} = await this.Chain.getFinalizedBlock();
|
|
484
|
+
|
|
485
|
+
const swapsOpened: {
|
|
486
|
+
[escrowHash: string]: {
|
|
487
|
+
data: Promise<StarknetSwapData | null>,
|
|
488
|
+
getInitTxId: () => Promise<string>,
|
|
489
|
+
getTxBlock: () => Promise<{
|
|
490
|
+
blockTime: number,
|
|
491
|
+
blockHeight: number
|
|
492
|
+
}>
|
|
493
|
+
}
|
|
494
|
+
} = {};
|
|
495
|
+
const resultingSwaps: {
|
|
496
|
+
[escrowHash: string]: {
|
|
497
|
+
init?: {
|
|
498
|
+
data: StarknetSwapData;
|
|
499
|
+
getInitTxId: () => Promise<string>;
|
|
500
|
+
getTxBlock: () => Promise<{ blockTime: number; blockHeight: number }>
|
|
501
|
+
};
|
|
502
|
+
state: SwapCommitState
|
|
503
|
+
}
|
|
504
|
+
} = {};
|
|
505
|
+
|
|
506
|
+
const promises: Promise<void>[] = [];
|
|
507
|
+
|
|
508
|
+
const processor = async (_event: StarknetAbiEvent<
|
|
509
|
+
EscrowManagerAbiType,
|
|
510
|
+
"escrow_manager::events::Initialize" | "escrow_manager::events::Claim" | "escrow_manager::events::Refund"
|
|
511
|
+
>) => {
|
|
512
|
+
const escrowHash = toHex(_event.params.escrow_hash).substring(2);
|
|
513
|
+
if(_event.name==="escrow_manager::events::Initialize") {
|
|
514
|
+
const event = _event as StarknetAbiEvent<EscrowManagerAbiType, "escrow_manager::events::Initialize">;
|
|
515
|
+
const claimHandlerHex = toHex(event.params.claim_handler);
|
|
516
|
+
const claimHandler = this.claimHandlersByAddress[claimHandlerHex];
|
|
517
|
+
if(claimHandler==null) {
|
|
518
|
+
logger.warn(`getHistoricalSwaps(Initialize): Unknown claim handler in tx ${event.txHash} with claim handler: `+claimHandlerHex);
|
|
519
|
+
return null;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
swapsOpened[escrowHash] = {
|
|
523
|
+
data: (async () => {
|
|
524
|
+
const txTrace = await this.Chain.Transactions.traceTransaction(event.txHash, event.blockHash);
|
|
525
|
+
if(txTrace==null) {
|
|
526
|
+
logger.warn(`getHistoricalSwaps(Initialize): Cannot get transaction trace for tx ${event.txHash}`);
|
|
527
|
+
return null;
|
|
528
|
+
}
|
|
529
|
+
const data = this.findInitSwapData(txTrace, event.params.escrow_hash, claimHandler);
|
|
530
|
+
if(data==null) {
|
|
531
|
+
logger.warn(`getHistoricalSwaps(Initialize): Cannot parse swap data from tx ${event.txHash} with escrow hash: `+escrowHash);
|
|
532
|
+
return null;
|
|
533
|
+
}
|
|
534
|
+
return data;
|
|
535
|
+
})(),
|
|
536
|
+
getInitTxId: () => Promise.resolve(event.txHash),
|
|
537
|
+
getTxBlock: async () => {
|
|
538
|
+
return {
|
|
539
|
+
blockHeight: event.blockNumber!,
|
|
540
|
+
blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber!)
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
if(_event.name==="escrow_manager::events::Claim") {
|
|
546
|
+
const event = _event as StarknetAbiEvent<EscrowManagerAbiType, "escrow_manager::events::Claim">;
|
|
547
|
+
const claimHandlerHex = toHex(event.params.claim_handler);
|
|
548
|
+
const claimHandler = this.claimHandlersByAddress[claimHandlerHex];
|
|
549
|
+
if(claimHandler==null) {
|
|
550
|
+
logger.warn(`getHistoricalSwaps(Claim): Unknown claim handler in tx ${event.txHash} with claim handler: `+claimHandlerHex);
|
|
551
|
+
return null;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
const foundSwapData = swapsOpened[escrowHash];
|
|
555
|
+
delete swapsOpened[escrowHash];
|
|
556
|
+
promises.push((async() => {
|
|
557
|
+
const data = await foundSwapData?.data;
|
|
558
|
+
resultingSwaps[escrowHash] = {
|
|
559
|
+
init: data==null ? undefined : {
|
|
560
|
+
data,
|
|
561
|
+
getInitTxId: foundSwapData.getInitTxId,
|
|
562
|
+
getTxBlock: foundSwapData.getTxBlock
|
|
563
|
+
},
|
|
564
|
+
state: {
|
|
565
|
+
type: SwapCommitStateType.PAID,
|
|
566
|
+
getClaimTxId: () => Promise.resolve(event.txHash),
|
|
567
|
+
getClaimResult: () => Promise.resolve(claimHandler.parseWitnessResult(event.params.witness_result)),
|
|
568
|
+
getTxBlock: async () => {
|
|
569
|
+
return {
|
|
570
|
+
blockHeight: event.blockNumber!,
|
|
571
|
+
blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber!)
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
})());
|
|
577
|
+
}
|
|
578
|
+
if(_event.name==="escrow_manager::events::Refund") {
|
|
579
|
+
const event = _event as StarknetAbiEvent<EscrowManagerAbiType, "escrow_manager::events::Refund">;
|
|
580
|
+
const foundSwapData = swapsOpened[escrowHash];
|
|
581
|
+
delete swapsOpened[escrowHash];
|
|
582
|
+
promises.push((async() => {
|
|
583
|
+
const data = await foundSwapData?.data;
|
|
584
|
+
const isExpired = data!=null && await this.isExpired(signer, data);
|
|
585
|
+
resultingSwaps[escrowHash] = {
|
|
586
|
+
init: data==null ? undefined : {
|
|
587
|
+
data,
|
|
588
|
+
getInitTxId: foundSwapData.getInitTxId,
|
|
589
|
+
getTxBlock: foundSwapData.getTxBlock
|
|
590
|
+
},
|
|
591
|
+
state: {
|
|
592
|
+
type: isExpired ? SwapCommitStateType.EXPIRED : SwapCommitStateType.NOT_COMMITED,
|
|
593
|
+
getRefundTxId: () => Promise.resolve(event.txHash),
|
|
594
|
+
getTxBlock: async () => {
|
|
595
|
+
return {
|
|
596
|
+
blockHeight: event.blockNumber!,
|
|
597
|
+
blockTime: await this.Chain.Blocks.getBlockTime(event.blockNumber!)
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
})());
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
//We have to fetch separately the different directions
|
|
607
|
+
await this.Events.findInContractEventsForward(
|
|
608
|
+
["escrow_manager::events::Initialize", "escrow_manager::events::Claim", "escrow_manager::events::Refund"],
|
|
609
|
+
[signer, null],
|
|
610
|
+
processor,
|
|
611
|
+
startBlockheight
|
|
612
|
+
);
|
|
613
|
+
await this.Events.findInContractEventsForward(
|
|
614
|
+
["escrow_manager::events::Initialize", "escrow_manager::events::Claim", "escrow_manager::events::Refund"],
|
|
615
|
+
[null, signer],
|
|
616
|
+
processor,
|
|
617
|
+
startBlockheight
|
|
618
|
+
)
|
|
619
|
+
|
|
620
|
+
for(let escrowHash in swapsOpened) {
|
|
621
|
+
const foundSwapData = swapsOpened[escrowHash];
|
|
622
|
+
const data = await foundSwapData.data;
|
|
623
|
+
if(data==null) continue;
|
|
624
|
+
resultingSwaps[escrowHash] = {
|
|
625
|
+
init: {
|
|
626
|
+
data,
|
|
627
|
+
getInitTxId: foundSwapData.getInitTxId,
|
|
628
|
+
getTxBlock: foundSwapData.getTxBlock
|
|
629
|
+
},
|
|
630
|
+
state: data.isOfferer(signer) && await this.isExpired(signer, data)
|
|
631
|
+
? {type: SwapCommitStateType.REFUNDABLE}
|
|
632
|
+
: {type: SwapCommitStateType.COMMITED}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
await Promise.all(promises);
|
|
637
|
+
|
|
638
|
+
logger.debug(`getHistoricalSwaps(): Found ${Object.keys(resultingSwaps).length} settled swaps!`);
|
|
639
|
+
logger.debug(`getHistoricalSwaps(): Found ${Object.keys(swapsOpened).length} unsettled swaps!`);
|
|
640
|
+
|
|
641
|
+
return {
|
|
642
|
+
swaps: resultingSwaps,
|
|
643
|
+
latestBlockheight: latestBlockheight ?? startBlockheight
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
|
|
449
647
|
////////////////////////////////////////////
|
|
450
648
|
//// Swap data initializer
|
|
451
649
|
/**
|
|
@@ -489,6 +687,44 @@ export class StarknetSwapContract
|
|
|
489
687
|
}));
|
|
490
688
|
}
|
|
491
689
|
|
|
690
|
+
/**
|
|
691
|
+
*
|
|
692
|
+
* @param call
|
|
693
|
+
* @param escrowHash
|
|
694
|
+
* @param claimHandler
|
|
695
|
+
* @private
|
|
696
|
+
*/
|
|
697
|
+
findInitSwapData(call: StarknetTraceCall, escrowHash: BigNumberish, claimHandler: IClaimHandler<any, any>): StarknetSwapData | null {
|
|
698
|
+
if(
|
|
699
|
+
BigInt(call.contract_address)===BigInt(this.contract.address) &&
|
|
700
|
+
BigInt(call.entry_point_selector)===this.initEntryPointSelector
|
|
701
|
+
) {
|
|
702
|
+
//Found, check correct escrow hash
|
|
703
|
+
const escrow = StarknetSwapData.fromSerializedFeltArray(call.calldata, claimHandler);
|
|
704
|
+
if(call.calldata.length < 1) throw new Error("Calldata invalid length");
|
|
705
|
+
const signatureLen = Number(toBigInt(call.calldata.shift()!));
|
|
706
|
+
if(call.calldata.length < signatureLen + 2) throw new Error("Calldata invalid length");
|
|
707
|
+
const _signature = call.calldata.splice(0, signatureLen);
|
|
708
|
+
const _timeout = toBigInt(call.calldata.shift()!);
|
|
709
|
+
const extraDataLen = Number(toBigInt(call.calldata.shift()!));
|
|
710
|
+
if(call.calldata.length < extraDataLen) throw new Error("Calldata invalid length");
|
|
711
|
+
const extraData = call.calldata.splice(0, extraDataLen);
|
|
712
|
+
if(call.calldata.length!==0) throw new Error("Calldata not read fully!");
|
|
713
|
+
|
|
714
|
+
if("0x"+escrow.getEscrowHash()===toHex(escrowHash)) {
|
|
715
|
+
if(extraData.length!==0) {
|
|
716
|
+
escrow.setExtraData(bytes31SpanToBuffer(extraData, 42).toString("hex"));
|
|
717
|
+
}
|
|
718
|
+
return escrow;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
for(let _call of call.calls) {
|
|
722
|
+
const found = this.findInitSwapData(_call, escrowHash, claimHandler);
|
|
723
|
+
if(found!=null) return found;
|
|
724
|
+
}
|
|
725
|
+
return null;
|
|
726
|
+
}
|
|
727
|
+
|
|
492
728
|
////////////////////////////////////////////
|
|
493
729
|
//// Utils
|
|
494
730
|
/**
|