UNPKG

@atomiqlabs/chain-starknet

Version:
260 lines (235 loc) 8.78 kB
import { SpvVaultClaimEvent, SpvVaultCloseEvent, SpvVaultData, SpvVaultDepositEvent, SpvVaultOpenEvent, SpvVaultTokenBalance, SpvVaultTokenData } from "@atomiqlabs/base"; import {BigNumberish} from "starknet"; import {Serialized, toBigInt, toHex} from "../../utils/Utils"; import {Buffer} from "buffer"; import {StarknetSpvWithdrawalData} from "./StarknetSpvWithdrawalData"; export type StarknetSpvVaultDataType = { relay_contract: BigNumberish, token_0: BigNumberish, token_1: BigNumberish, token_0_multiplier: BigNumberish, token_1_multiplier: BigNumberish, utxo: Record<number, boolean | object | BigNumberish>, confirmations: BigNumberish, withdraw_count: BigNumberish, deposit_count: BigNumberish, token_0_amount: BigNumberish, token_1_amount: BigNumberish }; export type StarknetSpvVaultDataCtorArgs = { owner: string, vaultId: bigint, struct: StarknetSpvVaultDataType, initialUtxo?: string }; function isSerializedData(obj: any): obj is ({type: "STARKNET"} & Serialized<StarknetSpvVaultData>) { return obj.type==="STARKNET"; } /** * Represents the state of the SPV vault (UTXO-controlled vault) * * @category Swaps */ export class StarknetSpvVaultData extends SpvVaultData<StarknetSpvWithdrawalData> { readonly owner: string; readonly vaultId: bigint; readonly relayContract: string; readonly token0: { token: string, multiplier: bigint, rawAmount: bigint } readonly token1: { token: string, multiplier: bigint, rawAmount: bigint }; readonly initialUtxo?: string; readonly confirmations: number; utxo: string; withdrawCount: number; depositCount: number; /** * Creates a new spv vault data based on the provided arguments * * @param args */ constructor(args: StarknetSpvVaultDataCtorArgs); /** * Deserializes the spv vault data from its serialized implementation (returned from {@link StarknetSpvVaultData.serialize}) * * @param data */ constructor(data: (Serialized<StarknetSpvVaultData> & {type: "STARKNET"})); constructor(data: StarknetSpvVaultDataCtorArgs | (Serialized<StarknetSpvVaultData> & {type: "STARKNET"})) { super(); if(!isSerializedData(data)) { if(data.vaultId==null) throw new Error("vaultId is null"); if(data.struct==null) throw new Error("state is null"); this.owner = data.owner; this.vaultId = data.vaultId; this.relayContract = toHex(data.struct.relay_contract); this.token0 = { token: toHex(data.struct.token_0), multiplier: toBigInt(data.struct.token_0_multiplier), rawAmount: toBigInt(data.struct.token_0_amount) }; this.token1 = { token: toHex(data.struct.token_1), multiplier: toBigInt(data.struct.token_1_multiplier), rawAmount: toBigInt(data.struct.token_1_amount) }; const txHash = Buffer.from(toBigInt(data.struct.utxo["0"] as BigNumberish).toString(16).padStart(64, "0"), "hex"); const vout = toBigInt(data.struct.utxo["1"] as BigNumberish); this.utxo = txHash.reverse().toString("hex")+":"+vout.toString(10); this.confirmations = Number(toBigInt(data.struct.confirmations)); this.withdrawCount = Number(toBigInt(data.struct.withdraw_count)); this.depositCount = Number(toBigInt(data.struct.deposit_count)); this.initialUtxo = data.initialUtxo; } else { this.owner = data.owner; this.vaultId = BigInt(data.vaultId); this.relayContract = data.relayContract; this.token0 = { token: data.token0.token, multiplier: BigInt(data.token0.multiplier), rawAmount: BigInt(data.token0.rawAmount) } this.token1 = { token: data.token1.token, multiplier: BigInt(data.token1.multiplier), rawAmount: BigInt(data.token1.rawAmount) }; this.utxo = data.utxo; this.confirmations = data.confirmations; this.withdrawCount = data.withdrawCount; this.depositCount = data.depositCount; this.initialUtxo = data.initialUtxo; } } /** * @inheritDoc */ getBalances(): SpvVaultTokenBalance[] { return [ {...this.token0, scaledAmount: this.token0.rawAmount * this.token0.multiplier}, {...this.token1, scaledAmount: this.token1.rawAmount * this.token1.multiplier} ]; } /** * @inheritDoc */ getConfirmations(): number { return this.confirmations; } /** * @inheritDoc */ getOwner(): string { return this.owner; } /** * @inheritDoc */ getTokenData(): SpvVaultTokenData[] { return [this.token0, this.token1]; } /** * @inheritDoc */ getUtxo(): string { return this.isOpened() ? this.utxo : this.initialUtxo!; } /** * @inheritDoc */ getVaultId(): bigint { return this.vaultId; } /** * @inheritDoc */ getWithdrawalCount(): number { return this.withdrawCount; } /** * @inheritDoc */ isOpened(): boolean { return this.utxo!=="0000000000000000000000000000000000000000000000000000000000000000:0"; } /** * @inheritDoc */ serialize(): (Serialized<StarknetSpvVaultData> & {type: "STARKNET"}) { return { type: "STARKNET", owner: this.owner, vaultId: this.vaultId.toString(10), relayContract: this.relayContract, token0: { token: this.token0.token, multiplier: this.token0.multiplier.toString(10), rawAmount: this.token0.rawAmount.toString(10) }, token1: { token: this.token1.token, multiplier: this.token1.multiplier.toString(10), rawAmount: this.token1.rawAmount.toString(10) }, utxo: this.utxo, confirmations: this.confirmations, withdrawCount: this.withdrawCount, depositCount: this.depositCount, initialUtxo: this.initialUtxo } } /** * @inheritDoc */ updateState(withdrawalTxOrEvent: SpvVaultClaimEvent | SpvVaultCloseEvent | SpvVaultOpenEvent | SpvVaultDepositEvent | StarknetSpvWithdrawalData): void { if(withdrawalTxOrEvent instanceof SpvVaultClaimEvent) { if(withdrawalTxOrEvent.withdrawCount <= this.withdrawCount) return; this.token0.rawAmount -= withdrawalTxOrEvent.amounts[0]; this.token1.rawAmount -= withdrawalTxOrEvent.amounts[1]; this.withdrawCount = withdrawalTxOrEvent.withdrawCount; this.utxo = withdrawalTxOrEvent.btcTxId+":0"; } if(withdrawalTxOrEvent instanceof SpvVaultCloseEvent) { this.token0.rawAmount = 0n; this.token1.rawAmount = 0n; this.utxo = "0000000000000000000000000000000000000000000000000000000000000000:0"; } if(withdrawalTxOrEvent instanceof SpvVaultOpenEvent) { if(this.isOpened()) return; this.utxo = withdrawalTxOrEvent.btcTxId+":"+withdrawalTxOrEvent.vout; } if(withdrawalTxOrEvent instanceof SpvVaultDepositEvent) { if(withdrawalTxOrEvent.depositCount <= this.depositCount) return; this.token0.rawAmount += withdrawalTxOrEvent.amounts[0]; this.token1.rawAmount += withdrawalTxOrEvent.amounts[1]; this.depositCount = withdrawalTxOrEvent.depositCount; } if(withdrawalTxOrEvent instanceof StarknetSpvWithdrawalData) { if(withdrawalTxOrEvent.getSpentVaultUtxo()!==this.utxo) return; const amounts = withdrawalTxOrEvent.getTotalOutput(); this.token0.rawAmount -= amounts[0]; this.token1.rawAmount -= amounts[1]; this.withdrawCount++; this.utxo = withdrawalTxOrEvent.btcTx.txid+":0"; } } /** * @inheritDoc */ getDepositCount(): number { return this.depositCount; } } SpvVaultData.deserializers["STARKNET"] = StarknetSpvVaultData;