UNPKG

ecash-agora

Version:

Library for interacting with the eCash Agora protocol

146 lines (135 loc) 4.47 kB
// Copyright (c) 2024 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. import { ChronikClient } from 'chronik-client'; import { ALL_BIP143, alpGenesis, alpSend, Ecc, emppScript, P2PKHSignatory, Script, shaRmd160, TxBuilder, TxBuilderInput, TxBuilderOutput, } from 'ecash-lib'; import { Wallet } from 'ecash-wallet'; import { expect } from 'chai'; import { AgoraPartial } from '../src/partial.js'; import { Agora, AgoraOffer } from '../src/agora.js'; export function makeAlpGenesis(params: { tokenType: number; fuelInput: TxBuilderInput; tokenAtomsArray: bigint[]; extraOutputs: TxBuilderOutput[]; }) { const { tokenType, fuelInput } = params; const txBuildGenesisGroup = new TxBuilder({ inputs: [fuelInput], outputs: [ { sats: 0n, script: emppScript([ alpGenesis( tokenType, { tokenTicker: `ALP token type ${tokenType}`, decimals: 4, }, { numBatons: 0, atomsArray: params.tokenAtomsArray, }, ), ]), }, ...params.extraOutputs, ], }); return txBuildGenesisGroup.sign(); } export async function makeAlpOffer(params: { chronik: ChronikClient; agoraPartial: AgoraPartial; makerSk: Uint8Array; fuelInput: TxBuilderInput; }): Promise<AgoraOffer> { const { chronik, agoraPartial, makerSk, fuelInput } = params; const makerPk = new Ecc().derivePubkey(makerSk); const makerPkh = shaRmd160(makerPk); const makerP2pkh = Script.p2pkh(makerPkh); const genesisOutputSats = 2000n; const genesisTx = makeAlpGenesis({ tokenType: agoraPartial.tokenType, fuelInput, tokenAtomsArray: [agoraPartial.offeredAtoms()], extraOutputs: [{ sats: genesisOutputSats, script: makerP2pkh }], }); const genesisTxid = (await chronik.broadcastTx(genesisTx.ser())).txid; const tokenId = genesisTxid; agoraPartial.tokenId = tokenId; expect((await chronik.token(tokenId)).tokenType.number).to.equal( agoraPartial.tokenType, ); const agoraScript = agoraPartial.script(); const agoraP2sh = Script.p2sh(shaRmd160(agoraScript.bytecode)); const txBuildOffer = new TxBuilder({ inputs: [ { input: { prevOut: { txid: genesisTxid, outIdx: 1, }, signData: { sats: genesisOutputSats, outputScript: makerP2pkh, }, }, signatory: P2PKHSignatory(makerSk, makerPk, ALL_BIP143), }, ], outputs: [ { sats: 0n, script: emppScript([ agoraPartial.adPushdata(), alpSend(tokenId, agoraPartial.tokenType, [ agoraPartial.offeredAtoms(), ]), ]), }, { sats: 546n, script: agoraP2sh }, ], }); const offerTx = txBuildOffer.sign(); await chronik.broadcastTx(offerTx.ser()); const agora = new Agora(chronik); expect(await agora.offeredFungibleTokenIds()).to.include(tokenId); const offers = await agora.activeOffersByTokenId(tokenId); expect(offers.length).to.equal(1); return offers[0]; } export async function takeAlpOffer(params: { chronik: ChronikClient; offer: AgoraOffer; takerSk: Uint8Array; acceptedAtoms: bigint; allowUnspendable?: boolean; }) { const takerSk = params.takerSk; const takerWallet = Wallet.fromSk(takerSk, params.chronik); const takerPk = takerWallet.pk; await takerWallet.sync(); const broadcastResult = await params.offer.take({ wallet: takerWallet, covenantSk: takerSk, covenantPk: takerPk, acceptedAtoms: params.acceptedAtoms, allowUnspendable: params.allowUnspendable, }); const acceptTxid = broadcastResult.broadcasted[0]; return acceptTxid; }