ecash-agora 2.2.0 → 2.5.0
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.
- package/README.md +12 -0
- package/dist/agora.d.ts +92 -2
- package/dist/agora.d.ts.map +1 -1
- package/dist/agora.js +103 -3
- package/dist/agora.js.map +1 -1
- package/package.json +4 -4
- package/tests/oneshot.test.ts +290 -0
- package/tests/partial-helper-alp.ts +10 -8
- package/tests/partial-helper-slp.ts +9 -8
- package/tests/partial.alp.bigsats.test.ts +10 -31
- package/tests/partial.alp.test.ts +42 -27
- package/tests/partial.slp.bigsats.test.ts +10 -31
- package/tests/partial.slp.test.ts +42 -28
package/tests/oneshot.test.ts
CHANGED
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
} from '../src/oneshot.js';
|
|
33
33
|
import { Agora, AgoraOffer } from '../src/agora.js';
|
|
34
34
|
import { EventEmitter, once } from 'node:events';
|
|
35
|
+
import { Wallet } from 'ecash-wallet/src/wallet.js';
|
|
35
36
|
|
|
36
37
|
use(chaiAsPromised);
|
|
37
38
|
|
|
@@ -704,4 +705,293 @@ describe('SLP', () => {
|
|
|
704
705
|
numPages: 1,
|
|
705
706
|
});
|
|
706
707
|
});
|
|
708
|
+
it('We can cancel an Agora Oneshot offer using cancel()', async () => {
|
|
709
|
+
// Create Agora object to access trades
|
|
710
|
+
const agora = new Agora(chronik);
|
|
711
|
+
|
|
712
|
+
const cancelerSk = fromHex('99'.repeat(32));
|
|
713
|
+
const cancelerWallet = Wallet.fromSk(cancelerSk, chronik);
|
|
714
|
+
|
|
715
|
+
const cancelerPk = cancelerWallet.pk;
|
|
716
|
+
|
|
717
|
+
const cancelerP2pkh = cancelerWallet.script;
|
|
718
|
+
|
|
719
|
+
await runner.sendToScript(50000n, cancelerP2pkh);
|
|
720
|
+
|
|
721
|
+
await cancelerWallet.sync();
|
|
722
|
+
|
|
723
|
+
const utxos = cancelerWallet.utxos;
|
|
724
|
+
expect(utxos.length).to.equal(1);
|
|
725
|
+
const utxo = utxos[0];
|
|
726
|
+
|
|
727
|
+
// 1. Seller creates an NFT1 GROUP token
|
|
728
|
+
const txBuildGenesisGroup = new TxBuilder({
|
|
729
|
+
inputs: [
|
|
730
|
+
{
|
|
731
|
+
input: {
|
|
732
|
+
prevOut: utxo.outpoint,
|
|
733
|
+
signData: {
|
|
734
|
+
sats: utxo.sats,
|
|
735
|
+
outputScript: cancelerP2pkh,
|
|
736
|
+
},
|
|
737
|
+
},
|
|
738
|
+
signatory: P2PKHSignatory(
|
|
739
|
+
cancelerSk,
|
|
740
|
+
cancelerPk,
|
|
741
|
+
ALL_BIP143,
|
|
742
|
+
),
|
|
743
|
+
},
|
|
744
|
+
],
|
|
745
|
+
outputs: [
|
|
746
|
+
{
|
|
747
|
+
sats: 0n,
|
|
748
|
+
script: slpGenesis(
|
|
749
|
+
SLP_NFT1_GROUP,
|
|
750
|
+
{
|
|
751
|
+
tokenTicker: 'SLP NFT1 GROUP TOKEN',
|
|
752
|
+
decimals: 4,
|
|
753
|
+
},
|
|
754
|
+
1n,
|
|
755
|
+
),
|
|
756
|
+
},
|
|
757
|
+
{ sats: 10000n, script: cancelerP2pkh },
|
|
758
|
+
],
|
|
759
|
+
});
|
|
760
|
+
const genesisTx = txBuildGenesisGroup.sign();
|
|
761
|
+
const genesisTxid = (await chronik.broadcastTx(genesisTx.ser())).txid;
|
|
762
|
+
const groupTokenId = genesisTxid;
|
|
763
|
+
|
|
764
|
+
expect(await chronik.token(genesisTxid)).to.deep.equal({
|
|
765
|
+
tokenId: groupTokenId,
|
|
766
|
+
tokenType: SLP_TOKEN_TYPE_NFT1_GROUP,
|
|
767
|
+
genesisInfo: {
|
|
768
|
+
tokenTicker: 'SLP NFT1 GROUP TOKEN',
|
|
769
|
+
tokenName: '',
|
|
770
|
+
url: '',
|
|
771
|
+
hash: '',
|
|
772
|
+
decimals: 4,
|
|
773
|
+
},
|
|
774
|
+
timeFirstSeen: 1300000000,
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
// 2. Seller creates an NFT1 CHILD token using the group token
|
|
778
|
+
const txBuildGenesisChild = new TxBuilder({
|
|
779
|
+
inputs: [
|
|
780
|
+
{
|
|
781
|
+
input: {
|
|
782
|
+
prevOut: {
|
|
783
|
+
txid: genesisTxid,
|
|
784
|
+
outIdx: 1,
|
|
785
|
+
},
|
|
786
|
+
signData: {
|
|
787
|
+
sats: 10000n,
|
|
788
|
+
outputScript: cancelerP2pkh,
|
|
789
|
+
},
|
|
790
|
+
},
|
|
791
|
+
signatory: P2PKHSignatory(
|
|
792
|
+
cancelerSk,
|
|
793
|
+
cancelerPk,
|
|
794
|
+
ALL_BIP143,
|
|
795
|
+
),
|
|
796
|
+
},
|
|
797
|
+
],
|
|
798
|
+
outputs: [
|
|
799
|
+
{
|
|
800
|
+
sats: 0n,
|
|
801
|
+
script: slpGenesis(
|
|
802
|
+
SLP_NFT1_CHILD,
|
|
803
|
+
{
|
|
804
|
+
tokenTicker: 'SLP NFT1 CHILD TOKEN',
|
|
805
|
+
decimals: 0,
|
|
806
|
+
},
|
|
807
|
+
1n,
|
|
808
|
+
),
|
|
809
|
+
},
|
|
810
|
+
{ sats: 8000n, script: cancelerP2pkh },
|
|
811
|
+
],
|
|
812
|
+
});
|
|
813
|
+
const genesisChildTx = txBuildGenesisChild.sign();
|
|
814
|
+
const genesisChildTxid = (
|
|
815
|
+
await chronik.broadcastTx(genesisChildTx.ser())
|
|
816
|
+
).txid;
|
|
817
|
+
const childTokenId = genesisChildTxid;
|
|
818
|
+
|
|
819
|
+
expect(await chronik.token(childTokenId)).to.deep.equal({
|
|
820
|
+
tokenId: childTokenId,
|
|
821
|
+
tokenType: SLP_TOKEN_TYPE_NFT1_CHILD,
|
|
822
|
+
genesisInfo: {
|
|
823
|
+
tokenTicker: 'SLP NFT1 CHILD TOKEN',
|
|
824
|
+
tokenName: '',
|
|
825
|
+
url: '',
|
|
826
|
+
hash: '',
|
|
827
|
+
decimals: 0,
|
|
828
|
+
},
|
|
829
|
+
timeFirstSeen: 1300000000,
|
|
830
|
+
});
|
|
831
|
+
|
|
832
|
+
const emitter = new EventEmitter();
|
|
833
|
+
const ws = chronik.ws({
|
|
834
|
+
onMessage: async msg => {
|
|
835
|
+
if (!emitter.emit('ws', msg)) {
|
|
836
|
+
console.warn('Emitted msg without any listeners', msg);
|
|
837
|
+
}
|
|
838
|
+
},
|
|
839
|
+
});
|
|
840
|
+
await ws.waitForOpen();
|
|
841
|
+
agora.subscribeWs(ws, {
|
|
842
|
+
type: 'TOKEN_ID',
|
|
843
|
+
tokenId: childTokenId,
|
|
844
|
+
});
|
|
845
|
+
const listenNext = () => once(emitter, 'ws') as Promise<[MsgTxClient]>;
|
|
846
|
+
|
|
847
|
+
// 3. Seller sends the NFT to an ad setup output for an Agora Oneshot
|
|
848
|
+
// covenant that asks for 80000 sats
|
|
849
|
+
const enforcedOutputs: TxOutput[] = [
|
|
850
|
+
{
|
|
851
|
+
sats: BigInt(0),
|
|
852
|
+
script: slpSend(childTokenId, SLP_NFT1_CHILD, [0n, 1n]),
|
|
853
|
+
},
|
|
854
|
+
{ sats: BigInt(80000), script: cancelerP2pkh },
|
|
855
|
+
];
|
|
856
|
+
const agoraOneshot = new AgoraOneshot({
|
|
857
|
+
enforcedOutputs,
|
|
858
|
+
cancelPk: cancelerPk,
|
|
859
|
+
});
|
|
860
|
+
const agoraAdScript = agoraOneshot.adScript();
|
|
861
|
+
const agoraAdP2sh = Script.p2sh(shaRmd160(agoraAdScript.bytecode));
|
|
862
|
+
const txBuildAdSetup = new TxBuilder({
|
|
863
|
+
inputs: [
|
|
864
|
+
{
|
|
865
|
+
input: {
|
|
866
|
+
prevOut: {
|
|
867
|
+
txid: genesisChildTxid,
|
|
868
|
+
outIdx: 1,
|
|
869
|
+
},
|
|
870
|
+
signData: {
|
|
871
|
+
sats: 8000n,
|
|
872
|
+
outputScript: cancelerP2pkh,
|
|
873
|
+
},
|
|
874
|
+
},
|
|
875
|
+
signatory: P2PKHSignatory(
|
|
876
|
+
cancelerSk,
|
|
877
|
+
cancelerPk,
|
|
878
|
+
ALL_BIP143,
|
|
879
|
+
),
|
|
880
|
+
},
|
|
881
|
+
],
|
|
882
|
+
outputs: [
|
|
883
|
+
{
|
|
884
|
+
sats: 0n,
|
|
885
|
+
script: slpSend(childTokenId, SLP_NFT1_CHILD, [1n]),
|
|
886
|
+
},
|
|
887
|
+
{ sats: 7000n, script: agoraAdP2sh },
|
|
888
|
+
],
|
|
889
|
+
});
|
|
890
|
+
const adSetupTx = txBuildAdSetup.sign();
|
|
891
|
+
const adSetupTxid = (await chronik.broadcastTx(adSetupTx.ser())).txid;
|
|
892
|
+
|
|
893
|
+
// 4. Seller finishes offer setup + sends NFT to the advertised P2SH
|
|
894
|
+
const agoraScript = agoraOneshot.script();
|
|
895
|
+
const agoraP2sh = Script.p2sh(shaRmd160(agoraScript.bytecode));
|
|
896
|
+
const txBuildOffer = new TxBuilder({
|
|
897
|
+
inputs: [
|
|
898
|
+
{
|
|
899
|
+
input: {
|
|
900
|
+
prevOut: {
|
|
901
|
+
txid: adSetupTxid,
|
|
902
|
+
outIdx: 1,
|
|
903
|
+
},
|
|
904
|
+
signData: {
|
|
905
|
+
sats: 7000n,
|
|
906
|
+
redeemScript: agoraAdScript,
|
|
907
|
+
},
|
|
908
|
+
},
|
|
909
|
+
signatory: AgoraOneshotAdSignatory(cancelerSk),
|
|
910
|
+
},
|
|
911
|
+
],
|
|
912
|
+
outputs: [
|
|
913
|
+
{
|
|
914
|
+
sats: 0n,
|
|
915
|
+
script: slpSend(childTokenId, SLP_NFT1_CHILD, [1n]),
|
|
916
|
+
},
|
|
917
|
+
{ sats: 546n, script: agoraP2sh },
|
|
918
|
+
],
|
|
919
|
+
});
|
|
920
|
+
const offerTx = txBuildOffer.sign();
|
|
921
|
+
const offerPromise = listenNext();
|
|
922
|
+
const offerTxid = (await chronik.broadcastTx(offerTx.ser())).txid;
|
|
923
|
+
const offerOutpoint: OutPoint = {
|
|
924
|
+
txid: offerTxid,
|
|
925
|
+
outIdx: 1,
|
|
926
|
+
};
|
|
927
|
+
const offerTxBuilderInput: TxInput = {
|
|
928
|
+
prevOut: offerOutpoint,
|
|
929
|
+
signData: {
|
|
930
|
+
redeemScript: agoraScript,
|
|
931
|
+
sats: 546n,
|
|
932
|
+
},
|
|
933
|
+
};
|
|
934
|
+
|
|
935
|
+
// Expected created offer
|
|
936
|
+
const expectedOffer = new AgoraOffer({
|
|
937
|
+
variant: {
|
|
938
|
+
type: 'ONESHOT',
|
|
939
|
+
params: agoraOneshot,
|
|
940
|
+
},
|
|
941
|
+
outpoint: offerOutpoint,
|
|
942
|
+
txBuilderInput: offerTxBuilderInput,
|
|
943
|
+
token: {
|
|
944
|
+
tokenId: childTokenId,
|
|
945
|
+
tokenType: SLP_TOKEN_TYPE_NFT1_CHILD,
|
|
946
|
+
atoms: 1n,
|
|
947
|
+
isMintBaton: false,
|
|
948
|
+
},
|
|
949
|
+
status: 'OPEN',
|
|
950
|
+
});
|
|
951
|
+
|
|
952
|
+
const [offerMsg] = await offerPromise;
|
|
953
|
+
expect(offerMsg.type).to.equal('Tx');
|
|
954
|
+
expect(offerMsg.msgType).to.equal('TX_ADDED_TO_MEMPOOL');
|
|
955
|
+
expect(offerMsg.txid).to.equal(offerTxid);
|
|
956
|
+
|
|
957
|
+
// 5. Buyer searches for NFT trades, finds the advertised one
|
|
958
|
+
expect(await agora.allOfferedTokenIds()).to.deep.equal([childTokenId]);
|
|
959
|
+
|
|
960
|
+
// Query by group token ID
|
|
961
|
+
expect(
|
|
962
|
+
await agora.activeOffersByGroupTokenId(groupTokenId),
|
|
963
|
+
).to.deep.equal([expectedOffer]);
|
|
964
|
+
|
|
965
|
+
// Query by child token ID
|
|
966
|
+
expect(await agora.activeOffersByTokenId(childTokenId)).to.deep.equal([
|
|
967
|
+
expectedOffer,
|
|
968
|
+
]);
|
|
969
|
+
|
|
970
|
+
// Query by cancelPk
|
|
971
|
+
expect(
|
|
972
|
+
await agora.activeOffersByPubKey(toHex(cancelerPk)),
|
|
973
|
+
).to.deep.equal([expectedOffer]);
|
|
974
|
+
|
|
975
|
+
// We can cancel the offer using cancel()
|
|
976
|
+
// We need a utxo to spend to cancel this offer
|
|
977
|
+
await runner.sendToScript(50000n, cancelerP2pkh);
|
|
978
|
+
await cancelerWallet.sync();
|
|
979
|
+
await expectedOffer.cancel({
|
|
980
|
+
wallet: cancelerWallet,
|
|
981
|
+
});
|
|
982
|
+
|
|
983
|
+
// We can no longer find the offer
|
|
984
|
+
expect(await agora.allOfferedTokenIds()).to.deep.equal([]);
|
|
985
|
+
expect(await agora.offeredGroupTokenIds()).to.deep.equal([]);
|
|
986
|
+
expect(await agora.offeredFungibleTokenIds()).to.deep.equal([]);
|
|
987
|
+
expect(
|
|
988
|
+
await agora.activeOffersByGroupTokenId(groupTokenId),
|
|
989
|
+
).to.deep.equal([]);
|
|
990
|
+
expect(await agora.activeOffersByTokenId(childTokenId)).to.deep.equal(
|
|
991
|
+
[],
|
|
992
|
+
);
|
|
993
|
+
expect(
|
|
994
|
+
await agora.activeOffersByPubKey(toHex(cancelerPk)),
|
|
995
|
+
).to.deep.equal([]);
|
|
996
|
+
});
|
|
707
997
|
});
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
TxBuilderInput,
|
|
17
17
|
TxBuilderOutput,
|
|
18
18
|
} from 'ecash-lib';
|
|
19
|
+
import { Wallet } from 'ecash-wallet';
|
|
19
20
|
import { expect } from 'chai';
|
|
20
21
|
|
|
21
22
|
import { AgoraPartial } from '../src/partial.js';
|
|
@@ -124,22 +125,23 @@ export async function takeAlpOffer(params: {
|
|
|
124
125
|
chronik: ChronikClient;
|
|
125
126
|
offer: AgoraOffer;
|
|
126
127
|
takerSk: Uint8Array;
|
|
127
|
-
takerInput: TxBuilderInput;
|
|
128
128
|
acceptedAtoms: bigint;
|
|
129
129
|
allowUnspendable?: boolean;
|
|
130
130
|
}) {
|
|
131
131
|
const takerSk = params.takerSk;
|
|
132
|
-
const
|
|
133
|
-
const
|
|
134
|
-
const takerP2pkh =
|
|
135
|
-
|
|
136
|
-
|
|
132
|
+
const takerWallet = Wallet.fromSk(takerSk, params.chronik);
|
|
133
|
+
const takerPk = takerWallet.pk;
|
|
134
|
+
const takerP2pkh = takerWallet.script;
|
|
135
|
+
|
|
136
|
+
await takerWallet.sync();
|
|
137
|
+
const broadcastResult = await params.offer.take({
|
|
138
|
+
wallet: takerWallet,
|
|
139
|
+
covenantSk: takerSk,
|
|
137
140
|
covenantPk: takerPk,
|
|
138
|
-
fuelInputs: [params.takerInput],
|
|
139
141
|
recipientScript: takerP2pkh,
|
|
140
142
|
acceptedAtoms: params.acceptedAtoms,
|
|
141
143
|
allowUnspendable: params.allowUnspendable,
|
|
142
144
|
});
|
|
143
|
-
const acceptTxid =
|
|
145
|
+
const acceptTxid = broadcastResult.broadcasted[0];
|
|
144
146
|
return acceptTxid;
|
|
145
147
|
}
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
TxBuilder,
|
|
15
15
|
TxBuilderInput,
|
|
16
16
|
} from 'ecash-lib';
|
|
17
|
+
import { Wallet } from 'ecash-wallet';
|
|
17
18
|
import { expect } from 'chai';
|
|
18
19
|
|
|
19
20
|
import { AgoraPartial, AgoraPartialAdSignatory } from '../src/partial.js';
|
|
@@ -132,22 +133,22 @@ export async function takeSlpOffer(params: {
|
|
|
132
133
|
chronik: ChronikClient;
|
|
133
134
|
offer: AgoraOffer;
|
|
134
135
|
takerSk: Uint8Array;
|
|
135
|
-
takerInput: TxBuilderInput;
|
|
136
136
|
acceptedAtoms: bigint;
|
|
137
137
|
allowUnspendable?: boolean;
|
|
138
138
|
}) {
|
|
139
139
|
const takerSk = params.takerSk;
|
|
140
|
-
const
|
|
141
|
-
const
|
|
142
|
-
const takerP2pkh =
|
|
143
|
-
|
|
144
|
-
|
|
140
|
+
const takerWallet = Wallet.fromSk(takerSk, params.chronik);
|
|
141
|
+
const takerPk = takerWallet.pk;
|
|
142
|
+
const takerP2pkh = takerWallet.script;
|
|
143
|
+
await takerWallet.sync();
|
|
144
|
+
const broadcastResult = await params.offer.take({
|
|
145
|
+
wallet: takerWallet,
|
|
146
|
+
covenantSk: takerSk,
|
|
145
147
|
covenantPk: takerPk,
|
|
146
|
-
fuelInputs: [params.takerInput],
|
|
147
148
|
recipientScript: takerP2pkh,
|
|
148
149
|
acceptedAtoms: params.acceptedAtoms,
|
|
149
150
|
allowUnspendable: params.allowUnspendable,
|
|
150
151
|
});
|
|
151
|
-
const acceptTxid =
|
|
152
|
+
const acceptTxid = broadcastResult.broadcasted[0];
|
|
152
153
|
return acceptTxid;
|
|
153
154
|
}
|
|
@@ -53,7 +53,10 @@ async function makeBuilderInputs(
|
|
|
53
53
|
runner: TestRunner,
|
|
54
54
|
values: bigint[],
|
|
55
55
|
): Promise<TxBuilderInput[]> {
|
|
56
|
-
const txid = await runner.
|
|
56
|
+
const txid = await runner.sendToTwoScripts(
|
|
57
|
+
{ script: makerScript, sats: values[0] },
|
|
58
|
+
{ script: takerScript, sats: values[1] },
|
|
59
|
+
);
|
|
57
60
|
return values.map((sats, outIdx) => ({
|
|
58
61
|
input: {
|
|
59
62
|
prevOut: {
|
|
@@ -84,10 +87,7 @@ describe('AgoraPartial ALP 7450M XEC vs 2p48-1 full accept', () => {
|
|
|
84
87
|
});
|
|
85
88
|
|
|
86
89
|
it('AgoraPartial ALP 7450M XEC vs 2p48-1 full accept', async () => {
|
|
87
|
-
const [fuelInput
|
|
88
|
-
10000n,
|
|
89
|
-
BIGSATS,
|
|
90
|
-
]);
|
|
90
|
+
const [fuelInput] = await makeBuilderInputs(runner, [10000n, BIGSATS]);
|
|
91
91
|
|
|
92
92
|
const agora = new Agora(chronik);
|
|
93
93
|
const agoraPartial = await agora.selectParams({
|
|
@@ -133,7 +133,6 @@ describe('AgoraPartial ALP 7450M XEC vs 2p48-1 full accept', () => {
|
|
|
133
133
|
chronik,
|
|
134
134
|
offer,
|
|
135
135
|
takerSk,
|
|
136
|
-
takerInput,
|
|
137
136
|
acceptedAtoms: agoraPartial.offeredAtoms(),
|
|
138
137
|
});
|
|
139
138
|
|
|
@@ -178,10 +177,7 @@ describe('AgoraPartial 7450M XEC vs 2p48-1 small accept', () => {
|
|
|
178
177
|
});
|
|
179
178
|
|
|
180
179
|
it('AgoraPartial ALP 7450M XEC vs 2p48-1 small accept', async () => {
|
|
181
|
-
const [fuelInput
|
|
182
|
-
10000n,
|
|
183
|
-
BIGSATS,
|
|
184
|
-
]);
|
|
180
|
+
const [fuelInput] = await makeBuilderInputs(runner, [10000n, BIGSATS]);
|
|
185
181
|
|
|
186
182
|
const agora = new Agora(chronik);
|
|
187
183
|
const agoraPartial = await agora.selectParams({
|
|
@@ -229,7 +225,6 @@ describe('AgoraPartial 7450M XEC vs 2p48-1 small accept', () => {
|
|
|
229
225
|
chronik,
|
|
230
226
|
offer,
|
|
231
227
|
takerSk,
|
|
232
|
-
takerInput,
|
|
233
228
|
acceptedAtoms,
|
|
234
229
|
});
|
|
235
230
|
|
|
@@ -282,10 +277,7 @@ describe('AgoraPartial 7450M XEC vs 2p47-1 full accept', () => {
|
|
|
282
277
|
});
|
|
283
278
|
|
|
284
279
|
it('AgoraPartial ALP 7450M XEC vs 2p47-1 full accept', async () => {
|
|
285
|
-
const [fuelInput
|
|
286
|
-
10000n,
|
|
287
|
-
BIGSATS,
|
|
288
|
-
]);
|
|
280
|
+
const [fuelInput] = await makeBuilderInputs(runner, [10000n, BIGSATS]);
|
|
289
281
|
|
|
290
282
|
const agora = new Agora(chronik);
|
|
291
283
|
const agoraPartial = await agora.selectParams({
|
|
@@ -330,7 +322,6 @@ describe('AgoraPartial 7450M XEC vs 2p47-1 full accept', () => {
|
|
|
330
322
|
chronik,
|
|
331
323
|
offer,
|
|
332
324
|
takerSk,
|
|
333
|
-
takerInput,
|
|
334
325
|
acceptedAtoms: agoraPartial.offeredAtoms(),
|
|
335
326
|
});
|
|
336
327
|
|
|
@@ -378,10 +369,7 @@ describe('AgoraPartial ALP 7450M XEC vs 2p47-1 small accept', () => {
|
|
|
378
369
|
});
|
|
379
370
|
|
|
380
371
|
it('AgoraPartial ALP 7450M XEC vs 2p47-1 small accept', async () => {
|
|
381
|
-
const [fuelInput
|
|
382
|
-
10000n,
|
|
383
|
-
BIGSATS,
|
|
384
|
-
]);
|
|
372
|
+
const [fuelInput] = await makeBuilderInputs(runner, [10000n, BIGSATS]);
|
|
385
373
|
|
|
386
374
|
const agora = new Agora(chronik);
|
|
387
375
|
const agoraPartial = await agora.selectParams({
|
|
@@ -429,7 +417,6 @@ describe('AgoraPartial ALP 7450M XEC vs 2p47-1 small accept', () => {
|
|
|
429
417
|
chronik,
|
|
430
418
|
offer,
|
|
431
419
|
takerSk,
|
|
432
|
-
takerInput,
|
|
433
420
|
acceptedAtoms,
|
|
434
421
|
});
|
|
435
422
|
|
|
@@ -482,10 +469,7 @@ describe('AgoraPartial ALP 7450M XEC vs 100 full accept', () => {
|
|
|
482
469
|
});
|
|
483
470
|
|
|
484
471
|
it('AgoraPartial ALP 7450M XEC vs 100 full accept', async () => {
|
|
485
|
-
const [fuelInput
|
|
486
|
-
10000n,
|
|
487
|
-
BIGSATS,
|
|
488
|
-
]);
|
|
472
|
+
const [fuelInput] = await makeBuilderInputs(runner, [10000n, BIGSATS]);
|
|
489
473
|
|
|
490
474
|
const agora = new Agora(chronik);
|
|
491
475
|
const agoraPartial = await agora.selectParams({
|
|
@@ -529,7 +513,6 @@ describe('AgoraPartial ALP 7450M XEC vs 100 full accept', () => {
|
|
|
529
513
|
chronik,
|
|
530
514
|
offer,
|
|
531
515
|
takerSk,
|
|
532
|
-
takerInput,
|
|
533
516
|
acceptedAtoms: 100n,
|
|
534
517
|
});
|
|
535
518
|
const acceptTx = await chronik.tx(acceptTxid);
|
|
@@ -574,10 +557,7 @@ describe('AgoraPartial ALP 7450M XEC vs 100 small accept', () => {
|
|
|
574
557
|
});
|
|
575
558
|
|
|
576
559
|
it('AgoraPartial ALP 7450M XEC vs 100 small accept', async () => {
|
|
577
|
-
const [fuelInput
|
|
578
|
-
10000n,
|
|
579
|
-
BIGSATS,
|
|
580
|
-
]);
|
|
560
|
+
const [fuelInput] = await makeBuilderInputs(runner, [10000n, BIGSATS]);
|
|
581
561
|
|
|
582
562
|
const agora = new Agora(chronik);
|
|
583
563
|
const agoraPartial = await agora.selectParams({
|
|
@@ -617,7 +597,6 @@ describe('AgoraPartial ALP 7450M XEC vs 100 small accept', () => {
|
|
|
617
597
|
chronik,
|
|
618
598
|
offer,
|
|
619
599
|
takerSk,
|
|
620
|
-
takerInput,
|
|
621
600
|
acceptedAtoms: 1n,
|
|
622
601
|
});
|
|
623
602
|
const acceptTx = await chronik.tx(acceptTxid);
|
|
@@ -24,6 +24,7 @@ import { TestRunner } from 'ecash-lib/dist/test/testRunner.js';
|
|
|
24
24
|
import { AgoraPartial } from '../src/partial.js';
|
|
25
25
|
import { makeAlpOffer, takeAlpOffer } from './partial-helper-alp.js';
|
|
26
26
|
import { Agora, TakenInfo } from '../src/agora.js';
|
|
27
|
+
import { Wallet } from 'ecash-wallet/src/wallet.js';
|
|
27
28
|
|
|
28
29
|
use(chaiAsPromised);
|
|
29
30
|
|
|
@@ -57,7 +58,10 @@ describe('AgoraPartial ALP', () => {
|
|
|
57
58
|
async function makeBuilderInputs(
|
|
58
59
|
values: bigint[],
|
|
59
60
|
): Promise<TxBuilderInput[]> {
|
|
61
|
+
// NB for these "not big sats" tests, we can just send to both, no need to sendToTwoScripts
|
|
60
62
|
const txid = await runner.sendToScript(values, makerScript);
|
|
63
|
+
// Send some cash to the taker, since the accept() tests spend from this wallet
|
|
64
|
+
await runner.sendToScript(values, takerScript);
|
|
61
65
|
return values.map((sats, outIdx) => ({
|
|
62
66
|
input: {
|
|
63
67
|
prevOut: {
|
|
@@ -417,6 +421,7 @@ describe('AgoraPartial ALP', () => {
|
|
|
417
421
|
},
|
|
418
422
|
];
|
|
419
423
|
|
|
424
|
+
let cancelTxsMatchCount = 0;
|
|
420
425
|
for (const testCase of TEST_CASES) {
|
|
421
426
|
it(`AgoraPartial ALP ${testCase.offeredAtoms} for ${testCase.info}`, async () => {
|
|
422
427
|
const agora = new Agora(chronik);
|
|
@@ -429,10 +434,7 @@ describe('AgoraPartial ALP', () => {
|
|
|
429
434
|
});
|
|
430
435
|
const askedSats = agoraPartial.askedSats(testCase.acceptedAtoms);
|
|
431
436
|
const requiredSats = askedSats + 2000n;
|
|
432
|
-
const [fuelInput
|
|
433
|
-
4000n,
|
|
434
|
-
requiredSats,
|
|
435
|
-
]);
|
|
437
|
+
const [fuelInput] = await makeBuilderInputs([4000n, requiredSats]);
|
|
436
438
|
|
|
437
439
|
const offer = await makeAlpOffer({
|
|
438
440
|
chronik,
|
|
@@ -444,12 +446,10 @@ describe('AgoraPartial ALP', () => {
|
|
|
444
446
|
chronik,
|
|
445
447
|
takerSk,
|
|
446
448
|
offer,
|
|
447
|
-
takerInput,
|
|
448
449
|
acceptedAtoms: testCase.acceptedAtoms,
|
|
449
450
|
allowUnspendable: testCase.allowUnspendable,
|
|
450
451
|
});
|
|
451
452
|
const acceptTx = await chronik.tx(acceptTxid);
|
|
452
|
-
// TODO we do not even get here, keep debugging
|
|
453
453
|
const offeredAtoms = agoraPartial.offeredAtoms();
|
|
454
454
|
const isFullAccept = testCase.acceptedAtoms == offeredAtoms;
|
|
455
455
|
if (isFullAccept) {
|
|
@@ -543,17 +543,40 @@ describe('AgoraPartial ALP', () => {
|
|
|
543
543
|
recipientScript: makerScript,
|
|
544
544
|
extraInputs: [fuelInput], // dummy input for measuring
|
|
545
545
|
});
|
|
546
|
-
const
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
const
|
|
555
|
-
|
|
556
|
-
|
|
546
|
+
const cancelTx = newOffer.cancelTx({
|
|
547
|
+
cancelSk: makerSk,
|
|
548
|
+
fuelInputs: await makeBuilderInputs([cancelFeeSats]),
|
|
549
|
+
recipientScript: makerScript,
|
|
550
|
+
});
|
|
551
|
+
const cancelTxid = cancelTx.txid();
|
|
552
|
+
|
|
553
|
+
// Let's build and broadcast using cancel() instead
|
|
554
|
+
const cancelWallet = Wallet.fromSk(makerSk, chronik);
|
|
555
|
+
await cancelWallet.sync();
|
|
556
|
+
const cancelResult = await newOffer.cancel({
|
|
557
|
+
wallet: cancelWallet,
|
|
558
|
+
});
|
|
559
|
+
const broadcastCancelTxid = cancelResult.broadcasted[0];
|
|
560
|
+
if (broadcastCancelTxid === cancelTxid) {
|
|
561
|
+
cancelTxsMatchCount++;
|
|
562
|
+
console.log(
|
|
563
|
+
`${cancelTxsMatchCount} of ${TEST_CASES.length} produce equal txids with cancelTx() and cancel()`,
|
|
564
|
+
);
|
|
565
|
+
|
|
566
|
+
// Between ~5 and ~8 of 46 of these txs are identical from each method
|
|
567
|
+
|
|
568
|
+
// On inspection, when cancel() txid does not match,
|
|
569
|
+
// it is because cancel has selected different fuel inputs
|
|
570
|
+
// This is expected behavior, these txs still show change
|
|
571
|
+
// going to the cancel wallet as expected
|
|
572
|
+
}
|
|
573
|
+
const cancelChronikTx = await chronik.tx(broadcastCancelTxid);
|
|
574
|
+
expect(cancelChronikTx.outputs[1].token?.atoms).to.equal(
|
|
575
|
+
leftoverTokens,
|
|
576
|
+
);
|
|
577
|
+
expect(cancelChronikTx.outputs[1].outputScript).to.equal(
|
|
578
|
+
makerScriptHex,
|
|
579
|
+
);
|
|
557
580
|
|
|
558
581
|
// takerIndex is 2 for full accept, 3 for partial accept
|
|
559
582
|
const takerIndex = isFullAccept ? 2 : 3;
|
|
@@ -611,10 +634,7 @@ describe('AgoraPartial ALP', () => {
|
|
|
611
634
|
});
|
|
612
635
|
const askedSats = agoraPartial.askedSats(thisTestCase.acceptedAtoms);
|
|
613
636
|
const requiredSats = askedSats + 2000n;
|
|
614
|
-
const [fuelInput
|
|
615
|
-
4000n,
|
|
616
|
-
requiredSats,
|
|
617
|
-
]);
|
|
637
|
+
const [fuelInput] = await makeBuilderInputs([4000n, requiredSats]);
|
|
618
638
|
|
|
619
639
|
const offer = await makeAlpOffer({
|
|
620
640
|
chronik,
|
|
@@ -639,7 +659,6 @@ describe('AgoraPartial ALP', () => {
|
|
|
639
659
|
chronik,
|
|
640
660
|
takerSk,
|
|
641
661
|
offer,
|
|
642
|
-
takerInput,
|
|
643
662
|
acceptedAtoms: thisTestCase.acceptedAtoms,
|
|
644
663
|
allowUnspendable: false,
|
|
645
664
|
}),
|
|
@@ -678,10 +697,7 @@ describe('AgoraPartial ALP', () => {
|
|
|
678
697
|
const acceptedAtoms = 500n;
|
|
679
698
|
const askedSats = agoraPartial.askedSats(acceptedAtoms);
|
|
680
699
|
const requiredSats = askedSats + 2000n;
|
|
681
|
-
const [fuelInput
|
|
682
|
-
4000n,
|
|
683
|
-
requiredSats,
|
|
684
|
-
]);
|
|
700
|
+
const [fuelInput] = await makeBuilderInputs([4000n, requiredSats]);
|
|
685
701
|
|
|
686
702
|
const offer = await makeAlpOffer({
|
|
687
703
|
chronik,
|
|
@@ -703,7 +719,6 @@ describe('AgoraPartial ALP', () => {
|
|
|
703
719
|
chronik,
|
|
704
720
|
takerSk,
|
|
705
721
|
offer,
|
|
706
|
-
takerInput,
|
|
707
722
|
acceptedAtoms: acceptedAtoms,
|
|
708
723
|
allowUnspendable: false,
|
|
709
724
|
}),
|