ecash-agora 0.1.1-rc

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.
@@ -0,0 +1,131 @@
1
+ // Copyright (c) 2024 The Bitcoin developers
2
+ // Distributed under the MIT software license, see the accompanying
3
+ // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
+
5
+ import { ChronikClient } from 'chronik-client';
6
+ import {
7
+ ALL_BIP143,
8
+ alpGenesis,
9
+ alpSend,
10
+ Ecc,
11
+ emppScript,
12
+ P2PKHSignatory,
13
+ Script,
14
+ shaRmd160,
15
+ TxBuilder,
16
+ TxBuilderInput,
17
+ } from 'ecash-lib';
18
+ import { expect } from 'chai';
19
+
20
+ import { AgoraPartial } from '../src/partial.js';
21
+ import { Agora, AgoraOffer } from '../src/agora.js';
22
+
23
+ export async function makeAlpOffer(params: {
24
+ chronik: ChronikClient;
25
+ ecc: Ecc;
26
+ agoraPartial: AgoraPartial;
27
+ makerSk: Uint8Array;
28
+ fuelInput: TxBuilderInput;
29
+ }): Promise<AgoraOffer> {
30
+ const { chronik, ecc, agoraPartial, makerSk, fuelInput } = params;
31
+ const makerPk = ecc.derivePubkey(makerSk);
32
+ const makerPkh = shaRmd160(makerPk);
33
+ const makerP2pkh = Script.p2pkh(makerPkh);
34
+
35
+ const genesisOutputSats = 2000;
36
+ const txBuildGenesisGroup = new TxBuilder({
37
+ inputs: [fuelInput],
38
+ outputs: [
39
+ {
40
+ value: 0,
41
+ script: emppScript([
42
+ alpGenesis(
43
+ agoraPartial.tokenType,
44
+ {
45
+ tokenTicker: `ALP token type ${agoraPartial.tokenType}`,
46
+ decimals: 4,
47
+ },
48
+ {
49
+ numBatons: 0,
50
+ amounts: [agoraPartial.offeredTokens()],
51
+ },
52
+ ),
53
+ ]),
54
+ },
55
+ { value: genesisOutputSats, script: makerP2pkh },
56
+ ],
57
+ });
58
+ const genesisTx = txBuildGenesisGroup.sign(ecc);
59
+ const genesisTxid = (await chronik.broadcastTx(genesisTx.ser())).txid;
60
+ const tokenId = genesisTxid;
61
+ agoraPartial.tokenId = tokenId;
62
+
63
+ expect((await chronik.token(tokenId)).tokenType.number).to.equal(
64
+ agoraPartial.tokenType,
65
+ );
66
+
67
+ const agoraScript = agoraPartial.script();
68
+ const agoraP2sh = Script.p2sh(shaRmd160(agoraScript.bytecode));
69
+ const txBuildOffer = new TxBuilder({
70
+ inputs: [
71
+ {
72
+ input: {
73
+ prevOut: {
74
+ txid: genesisTxid,
75
+ outIdx: 1,
76
+ },
77
+ signData: {
78
+ value: genesisOutputSats,
79
+ outputScript: makerP2pkh,
80
+ },
81
+ },
82
+ signatory: P2PKHSignatory(makerSk, makerPk, ALL_BIP143),
83
+ },
84
+ ],
85
+ outputs: [
86
+ {
87
+ value: 0,
88
+ script: emppScript([
89
+ agoraPartial.adPushdata(),
90
+ alpSend(tokenId, agoraPartial.tokenType, [
91
+ agoraPartial.offeredTokens(),
92
+ ]),
93
+ ]),
94
+ },
95
+ { value: 546, script: agoraP2sh },
96
+ ],
97
+ });
98
+ const offerTx = txBuildOffer.sign(ecc);
99
+ await chronik.broadcastTx(offerTx.ser());
100
+
101
+ const agora = new Agora(chronik);
102
+ expect(await agora.offeredFungibleTokenIds()).to.include(tokenId);
103
+ const offers = await agora.activeOffersByTokenId(tokenId);
104
+ expect(offers.length).to.equal(1);
105
+
106
+ return offers[0];
107
+ }
108
+
109
+ export async function takeAlpOffer(params: {
110
+ chronik: ChronikClient;
111
+ ecc: Ecc;
112
+ offer: AgoraOffer;
113
+ takerSk: Uint8Array;
114
+ takerInput: TxBuilderInput;
115
+ acceptedTokens: bigint;
116
+ }) {
117
+ const takerSk = params.takerSk;
118
+ const takerPk = params.ecc.derivePubkey(takerSk);
119
+ const takerPkh = shaRmd160(takerPk);
120
+ const takerP2pkh = Script.p2pkh(takerPkh);
121
+ const acceptTx = params.offer.acceptTx({
122
+ ecc: params.ecc,
123
+ covenantSk: params.takerSk,
124
+ covenantPk: takerPk,
125
+ fuelInputs: [params.takerInput],
126
+ recipientScript: takerP2pkh,
127
+ acceptedTokens: params.acceptedTokens,
128
+ });
129
+ const acceptTxid = (await params.chronik.broadcastTx(acceptTx.ser())).txid;
130
+ return acceptTxid;
131
+ }
@@ -0,0 +1,154 @@
1
+ // Copyright (c) 2024 The Bitcoin developers
2
+ // Distributed under the MIT software license, see the accompanying
3
+ // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
+
5
+ import { ChronikClient } from 'chronik-client';
6
+ import {
7
+ ALL_BIP143,
8
+ Ecc,
9
+ P2PKHSignatory,
10
+ Script,
11
+ shaRmd160,
12
+ slpGenesis,
13
+ slpSend,
14
+ TxBuilder,
15
+ TxBuilderInput,
16
+ } from 'ecash-lib';
17
+ import { expect } from 'chai';
18
+
19
+ import { AgoraPartial, AgoraPartialAdSignatory } from '../src/partial.js';
20
+ import { Agora, AgoraOffer } from '../src/agora.js';
21
+
22
+ export async function makeSlpOffer(params: {
23
+ chronik: ChronikClient;
24
+ ecc: Ecc;
25
+ agoraPartial: AgoraPartial;
26
+ makerSk: Uint8Array;
27
+ fuelInput: TxBuilderInput;
28
+ }): Promise<AgoraOffer> {
29
+ const { chronik, ecc, agoraPartial, makerSk, fuelInput } = params;
30
+ const makerPk = ecc.derivePubkey(makerSk);
31
+ const makerPkh = shaRmd160(makerPk);
32
+ const makerP2pkh = Script.p2pkh(makerPkh);
33
+
34
+ const genesisOutputSats = 2000;
35
+ const txBuildGenesisGroup = new TxBuilder({
36
+ inputs: [fuelInput],
37
+ outputs: [
38
+ {
39
+ value: 0,
40
+ script: slpGenesis(
41
+ agoraPartial.tokenType,
42
+ {
43
+ tokenTicker: `SLP token type ${agoraPartial.tokenType}`,
44
+ decimals: 4,
45
+ },
46
+ agoraPartial.offeredTokens(),
47
+ ),
48
+ },
49
+ { value: genesisOutputSats, script: makerP2pkh },
50
+ ],
51
+ });
52
+ const genesisTx = txBuildGenesisGroup.sign(ecc);
53
+ const genesisTxid = (await chronik.broadcastTx(genesisTx.ser())).txid;
54
+ const tokenId = genesisTxid;
55
+ agoraPartial.tokenId = tokenId;
56
+
57
+ expect((await chronik.token(tokenId)).tokenType.number).to.equal(
58
+ agoraPartial.tokenType,
59
+ );
60
+
61
+ const adSetupSats = 1000n;
62
+ const agoraAdScript = agoraPartial.adScript();
63
+ const agoraAdP2sh = Script.p2sh(shaRmd160(agoraAdScript.bytecode));
64
+ const txBuildAdSetup = new TxBuilder({
65
+ inputs: [
66
+ {
67
+ input: {
68
+ prevOut: {
69
+ txid: genesisTxid,
70
+ outIdx: 1,
71
+ },
72
+ signData: {
73
+ value: genesisOutputSats,
74
+ outputScript: makerP2pkh,
75
+ },
76
+ },
77
+ signatory: P2PKHSignatory(makerSk, makerPk, ALL_BIP143),
78
+ },
79
+ ],
80
+ outputs: [
81
+ {
82
+ value: 0,
83
+ script: slpSend(tokenId, agoraPartial.tokenType, [
84
+ agoraPartial.offeredTokens(),
85
+ ]),
86
+ },
87
+ { value: adSetupSats, script: agoraAdP2sh },
88
+ ],
89
+ });
90
+ const adSetupTx = txBuildAdSetup.sign(ecc);
91
+ const adSetupTxid = (await chronik.broadcastTx(adSetupTx.ser())).txid;
92
+
93
+ const agoraScript = agoraPartial.script();
94
+ const agoraP2sh = Script.p2sh(shaRmd160(agoraScript.bytecode));
95
+ const txBuildOffer = new TxBuilder({
96
+ inputs: [
97
+ {
98
+ input: {
99
+ prevOut: {
100
+ txid: adSetupTxid,
101
+ outIdx: 1,
102
+ },
103
+ signData: {
104
+ value: adSetupSats,
105
+ redeemScript: agoraAdScript,
106
+ },
107
+ },
108
+ signatory: AgoraPartialAdSignatory(makerSk),
109
+ },
110
+ ],
111
+ outputs: [
112
+ {
113
+ value: 0,
114
+ script: slpSend(tokenId, agoraPartial.tokenType, [
115
+ agoraPartial.offeredTokens(),
116
+ ]),
117
+ },
118
+ { value: 546, script: agoraP2sh },
119
+ ],
120
+ });
121
+ const offerTx = txBuildOffer.sign(ecc);
122
+ await chronik.broadcastTx(offerTx.ser());
123
+
124
+ const agora = new Agora(chronik);
125
+ expect(await agora.offeredFungibleTokenIds()).to.include(tokenId);
126
+ const offers = await agora.activeOffersByTokenId(tokenId);
127
+ expect(offers.length).to.equal(1);
128
+
129
+ return offers[0];
130
+ }
131
+
132
+ export async function takeSlpOffer(params: {
133
+ chronik: ChronikClient;
134
+ ecc: Ecc;
135
+ offer: AgoraOffer;
136
+ takerSk: Uint8Array;
137
+ takerInput: TxBuilderInput;
138
+ acceptedTokens: bigint;
139
+ }) {
140
+ const takerSk = params.takerSk;
141
+ const takerPk = params.ecc.derivePubkey(takerSk);
142
+ const takerPkh = shaRmd160(takerPk);
143
+ const takerP2pkh = Script.p2pkh(takerPkh);
144
+ const acceptTx = params.offer.acceptTx({
145
+ ecc: params.ecc,
146
+ covenantSk: params.takerSk,
147
+ covenantPk: takerPk,
148
+ fuelInputs: [params.takerInput],
149
+ recipientScript: takerP2pkh,
150
+ acceptedTokens: params.acceptedTokens,
151
+ });
152
+ const acceptTxid = (await params.chronik.broadcastTx(acceptTx.ser())).txid;
153
+ return acceptTxid;
154
+ }