import { LoadByOriginInstruction, LoadInstruction } from "@aldea/core/instructions"; import { Address, CommitTxResponse, CreateTxCallback, HDPrivKey, OpCode, Output, Pointer, PrivKey, Tx, TxBuilderOpts, base16, } from "@aldea/sdk" import {COIN_CLASS_PTR} from "./constants.js"; import {AldeaClient} from "./aldea-client.js"; export abstract class Wallet { protected client: AldeaClient constructor (client: AldeaClient) { this.client = client } abstract getNextAddress(): Promise
abstract getInventory(): Promise> abstract signTx(partialTx: Tx, updateSigs?: PrivKey | HDPrivKey | Array): Promise abstract saveTxExec(tx: Tx, outputList: Output[]): Promise abstract addUtxo(output: Output): Promise abstract sync(): Promise async fundTx(partialTx: Tx): Promise { const outputs = await this.getInventory() const coinOutputs = outputs.filter(o => { return o.classPtr.equals(COIN_CLASS_PTR) && !partialTx.instructions.some(i => { return ( i.opcode === OpCode.LOAD && o.id === base16.encode((i).outputId) ) || ( i.opcode === OpCode.LOADBYORIGIN && o.origin.equals(Pointer.fromBytes((i).origin)) ) }) }) return await this.client.createTx({ extend: partialTx }, async (txb) => { let motosIn = 0n for (const coin of coinOutputs) { if (coin.props?.amount) { const coinRef = txb.load(coin.id) motosIn += coin.props.amount if (motosIn > 100n) { const changeAddr = await this.getNextAddress() const changeRef = txb.call(coinRef, 'send', [motosIn - 100n]) txb.lock(changeRef, changeAddr) motosIn = 100n } txb.fund(coinRef) } if (motosIn === 100n) { break } } }) } async commitTx(tx: Tx): Promise { const response = await this.client.commitTx(tx) const outputs = response.outputs.map(o =>Output.fromJson(o)) await this.saveTxExec(tx, outputs) return response } async createFundedTx(builder: CreateTxCallback): Promise; async createFundedTx(opts: TxBuilderOpts, builder: CreateTxCallback): Promise; async createFundedTx(optsOrBuilder: TxBuilderOpts | CreateTxCallback, builder?: CreateTxCallback): Promise { let opts: TxBuilderOpts if (typeof optsOrBuilder === 'function') { opts = {} builder = optsOrBuilder as CreateTxCallback } else { opts = optsOrBuilder builder = builder as CreateTxCallback } const userTx = await this.client.createTx(opts, builder) const fundedTx = await this.fundTx(userTx) return this.signTx(fundedTx, opts.updateSigs) } }