@atomiqlabs/chain-starknet
Version:
Starknet specific base implementation
150 lines (121 loc) • 5.72 kB
text/typescript
import {Provider, constants, stark, ec} from "starknet";
import {getLogger, toHex} from "../../utils/Utils";
import {StarknetTransactions, StarknetTx} from "./modules/StarknetTransactions";
import {StarknetFees} from "./modules/StarknetFees";
import {StarknetAddresses} from "./modules/StarknetAddresses";
import {StarknetTokens} from "./modules/StarknetTokens";
import {StarknetEvents} from "./modules/StarknetEvents";
import {StarknetSignatures} from "./modules/StarknetSignatures";
import {StarknetAccounts} from "./modules/StarknetAccounts";
import {StarknetBlocks} from "./modules/StarknetBlocks";
import {ChainInterface, TransactionConfirmationOptions} from "@atomiqlabs/base";
import {StarknetSigner} from "../wallet/StarknetSigner";
import {Buffer} from "buffer";
import {StarknetKeypairWallet} from "../wallet/StarknetKeypairWallet";
export type StarknetRetryPolicy = {
maxRetries?: number,
delay?: number,
exponential?: boolean
}
export class StarknetChainInterface implements ChainInterface {
readonly chainId = "STARKNET";
readonly provider: Provider;
readonly retryPolicy: StarknetRetryPolicy;
public readonly starknetChainId: constants.StarknetChainId;
public Fees: StarknetFees;
public readonly Tokens: StarknetTokens;
public readonly Transactions: StarknetTransactions;
public readonly Signatures: StarknetSignatures;
public readonly Events: StarknetEvents;
public readonly Accounts: StarknetAccounts;
public readonly Blocks: StarknetBlocks;
protected readonly logger = getLogger("StarknetChainInterface: ");
constructor(
chainId: constants.StarknetChainId,
provider: Provider,
retryPolicy?: StarknetRetryPolicy,
solanaFeeEstimator: StarknetFees = new StarknetFees(provider)
) {
this.starknetChainId = chainId;
this.provider = provider;
this.retryPolicy = retryPolicy;
this.Fees = solanaFeeEstimator;
this.Tokens = new StarknetTokens(this);
this.Transactions = new StarknetTransactions(this);
this.Signatures = new StarknetSignatures(this);
this.Events = new StarknetEvents(this);
this.Accounts = new StarknetAccounts(this);
this.Blocks = new StarknetBlocks(this);
}
async getBalance(signer: string, tokenAddress: string): Promise<bigint> {
//TODO: For native token we should discount the cost of deploying an account if it is not deployed yet
return await this.Tokens.getTokenBalance(signer, tokenAddress);
}
getNativeCurrencyAddress(): string {
return this.Tokens.getNativeCurrencyAddress();
}
isValidToken(tokenIdentifier: string): boolean {
return this.Tokens.isValidToken(tokenIdentifier);
}
isValidAddress(address: string): boolean {
return StarknetAddresses.isValidAddress(address);
}
///////////////////////////////////
//// Callbacks & handlers
offBeforeTxReplace(callback: (oldTx: string, oldTxId: string, newTx: string, newTxId: string) => Promise<void>): boolean {
return true;
}
onBeforeTxReplace(callback: (oldTx: string, oldTxId: string, newTx: string, newTxId: string) => Promise<void>): void {}
onBeforeTxSigned(callback: (tx: StarknetTx) => Promise<void>): void {
this.Transactions.onBeforeTxSigned(callback);
}
offBeforeTxSigned(callback: (tx: StarknetTx) => Promise<void>): boolean {
return this.Transactions.offBeforeTxSigned(callback);
}
randomAddress(): string {
return toHex(stark.randomAddress());
}
randomSigner(): StarknetSigner {
const privateKey = "0x"+Buffer.from(ec.starkCurve.utils.randomPrivateKey()).toString("hex");
const wallet = new StarknetKeypairWallet(this.provider, privateKey);
return new StarknetSigner(wallet);
}
////////////////////////////////////////////
//// Transactions
sendAndConfirm(
signer: StarknetSigner,
txs: StarknetTx[],
waitForConfirmation?: boolean,
abortSignal?: AbortSignal,
parallel?: boolean,
onBeforePublish?: (txId: string, rawTx: string) => Promise<void>
): Promise<string[]> {
return this.Transactions.sendAndConfirm(signer, txs, waitForConfirmation, abortSignal, parallel, onBeforePublish);
}
serializeTx(tx: StarknetTx): Promise<string> {
return this.Transactions.serializeTx(tx);
}
deserializeTx(txData: string): Promise<StarknetTx> {
return this.Transactions.deserializeTx(txData);
}
getTxIdStatus(txId: string): Promise<"not_found" | "pending" | "success" | "reverted"> {
return this.Transactions.getTxIdStatus(txId);
}
getTxStatus(tx: string): Promise<"not_found" | "pending" | "success" | "reverted"> {
return this.Transactions.getTxStatus(tx);
}
txsTransfer(signer: string, token: string, amount: bigint, dstAddress: string, feeRate?: string): Promise<StarknetTx[]> {
return this.Tokens.txsTransfer(signer, token, amount, dstAddress, feeRate);
}
async transfer(
signer: StarknetSigner,
token: string,
amount: bigint,
dstAddress: string,
txOptions?: TransactionConfirmationOptions
): Promise<string> {
const txs = await this.Tokens.txsTransfer(signer.getAddress(), token, amount, dstAddress, txOptions?.feeRate);
const [txId] = await this.Transactions.sendAndConfirm(signer, txs, txOptions?.waitForConfirmation, txOptions?.abortSignal, false);
return txId;
}
}