mainnet-js 1.1.34 → 2.0.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/dist/index.html +1 -1
- package/dist/{mainnet-1.1.34.js → mainnet-2.0.0.js} +25 -337
- package/dist/module/db/SqlProvider.d.ts +2 -2
- package/dist/module/db/SqlProvider.d.ts.map +1 -1
- package/dist/module/db/SqlProvider.js +6 -24
- package/dist/module/db/SqlProvider.js.map +1 -1
- package/dist/module/index.d.ts +0 -3
- package/dist/module/index.d.ts.map +1 -1
- package/dist/module/index.js +3 -6
- package/dist/module/index.js.map +1 -1
- package/dist/module/transaction/Wif.d.ts +4 -8
- package/dist/module/transaction/Wif.d.ts.map +1 -1
- package/dist/module/transaction/Wif.js +6 -10
- package/dist/module/transaction/Wif.js.map +1 -1
- package/dist/module/util/deriveCashaddr.d.ts +1 -0
- package/dist/module/util/deriveCashaddr.d.ts.map +1 -1
- package/dist/module/util/deriveCashaddr.js +8 -1
- package/dist/module/util/deriveCashaddr.js.map +1 -1
- package/dist/module/wallet/Base.d.ts +1 -1
- package/dist/module/wallet/Base.js +1 -1
- package/dist/module/wallet/Util.d.ts +2 -2
- package/dist/module/wallet/Util.js +2 -2
- package/dist/module/wallet/Wif.d.ts +0 -28
- package/dist/module/wallet/Wif.d.ts.map +1 -1
- package/dist/module/wallet/Wif.js +2 -109
- package/dist/module/wallet/Wif.js.map +1 -1
- package/dist/module/wallet/createWallet.d.ts +0 -12
- package/dist/module/wallet/createWallet.d.ts.map +1 -1
- package/dist/module/wallet/createWallet.js +0 -43
- package/dist/module/wallet/createWallet.js.map +1 -1
- package/dist/module/wallet/interface.d.ts +0 -2
- package/dist/module/wallet/interface.d.ts.map +1 -1
- package/dist/module/webhook/Webhook.d.ts +1 -6
- package/dist/module/webhook/Webhook.d.ts.map +1 -1
- package/dist/module/webhook/Webhook.js +0 -4
- package/dist/module/webhook/Webhook.js.map +1 -1
- package/dist/module/webhook/index.d.ts +0 -1
- package/dist/module/webhook/index.d.ts.map +1 -1
- package/dist/module/webhook/index.js +0 -1
- package/dist/module/webhook/index.js.map +1 -1
- package/dist/module/webhook/interface.d.ts +0 -1
- package/dist/module/webhook/interface.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -10
- package/src/db/SqlProvider.test.ts +2 -18
- package/src/db/SqlProvider.ts +5 -26
- package/src/index.ts +3 -7
- package/src/transaction/Wif.ts +2 -19
- package/src/util/deriveCashaddr.test.ts +8 -0
- package/src/util/deriveCashaddr.ts +9 -0
- package/src/wallet/Base.ts +1 -1
- package/src/wallet/Util.ts +2 -2
- package/src/wallet/Wif.test.ts +0 -23
- package/src/wallet/Wif.ts +2 -148
- package/src/wallet/createWallet.ts +0 -53
- package/src/wallet/interface.ts +0 -2
- package/src/webhook/Webhook.ts +4 -10
- package/src/webhook/index.ts +0 -1
- package/src/webhook/interface.ts +0 -1
- package/webpack.config.cjs +7 -7
- package/dist/module/slp/GsppProvider.d.ts +0 -55
- package/dist/module/slp/GsppProvider.d.ts.map +0 -1
- package/dist/module/slp/GsppProvider.js +0 -204
- package/dist/module/slp/GsppProvider.js.map +0 -1
- package/dist/module/slp/SlpDbProvider.d.ts +0 -52
- package/dist/module/slp/SlpDbProvider.d.ts.map +0 -1
- package/dist/module/slp/SlpDbProvider.js +0 -175
- package/dist/module/slp/SlpDbProvider.js.map +0 -1
- package/dist/module/slp/SlpDbTemplates.d.ts +0 -313
- package/dist/module/slp/SlpDbTemplates.d.ts.map +0 -1
- package/dist/module/slp/SlpDbTemplates.js +0 -375
- package/dist/module/slp/SlpDbTemplates.js.map +0 -1
- package/dist/module/slp/SlpLibAuth.d.ts +0 -210
- package/dist/module/slp/SlpLibAuth.d.ts.map +0 -1
- package/dist/module/slp/SlpLibAuth.js +0 -451
- package/dist/module/slp/SlpLibAuth.js.map +0 -1
- package/dist/module/slp/SlpProvider.d.ts +0 -24
- package/dist/module/slp/SlpProvider.d.ts.map +0 -1
- package/dist/module/slp/SlpProvider.js +0 -29
- package/dist/module/slp/SlpProvider.js.map +0 -1
- package/dist/module/slp/index.d.ts +0 -6
- package/dist/module/slp/index.d.ts.map +0 -1
- package/dist/module/slp/index.js +0 -5
- package/dist/module/slp/index.js.map +0 -1
- package/dist/module/slp/interface.d.ts +0 -114
- package/dist/module/slp/interface.d.ts.map +0 -1
- package/dist/module/slp/interface.js +0 -7
- package/dist/module/slp/interface.js.map +0 -1
- package/dist/module/util/bchaddr.d.ts +0 -2
- package/dist/module/util/bchaddr.d.ts.map +0 -1
- package/dist/module/util/bchaddr.js +0 -16
- package/dist/module/util/bchaddr.js.map +0 -1
- package/dist/module/wallet/Slp.d.ts +0 -431
- package/dist/module/wallet/Slp.d.ts.map +0 -1
- package/dist/module/wallet/Slp.js +0 -770
- package/dist/module/wallet/Slp.js.map +0 -1
- package/dist/module/webhook/WebhookSlp.d.ts +0 -15
- package/dist/module/webhook/WebhookSlp.d.ts.map +0 -1
- package/dist/module/webhook/WebhookSlp.js +0 -100
- package/dist/module/webhook/WebhookSlp.js.map +0 -1
- package/src/slp/GsppProvider.test.ts +0 -40
- package/src/slp/GsppProvider.ts +0 -329
- package/src/slp/SlpDbProvider.test.ts +0 -27
- package/src/slp/SlpDbProvider.ts +0 -291
- package/src/slp/SlpDbTemplates.ts +0 -400
- package/src/slp/SlpLibAuth.test.ts +0 -162
- package/src/slp/SlpLibAuth.ts +0 -532
- package/src/slp/SlpProvider.ts +0 -100
- package/src/slp/index.ts +0 -6
- package/src/slp/interface.ts +0 -128
- package/src/util/bchaddr.test.ts +0 -27
- package/src/util/bchaddr.ts +0 -27
- package/src/wallet/Slp.test.headless.js +0 -120
- package/src/wallet/Slp.test.ts +0 -1000
- package/src/wallet/Slp.ts +0 -1014
- package/src/webhook/WebhookSlp.test.ts +0 -288
- package/src/webhook/WebhookSlp.ts +0 -123
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import { binToHex } from "@bitauth/libauth";
|
|
2
|
-
import { parseSLP } from "slp-parser";
|
|
3
|
-
import { DUST_UTXO_THRESHOLD } from "../constant";
|
|
4
|
-
import {
|
|
5
|
-
SlpGetGenesisOutputs,
|
|
6
|
-
SlpGetMintOutputs,
|
|
7
|
-
SlpGetSendOutputs,
|
|
8
|
-
} from "../slp/SlpLibAuth";
|
|
9
|
-
import {
|
|
10
|
-
SlpGenesisOptions,
|
|
11
|
-
SlpSendRequest,
|
|
12
|
-
SlpTokenType,
|
|
13
|
-
} from "../slp/interface";
|
|
14
|
-
import { RegTestWallet } from "../wallet/Wif";
|
|
15
|
-
import { SlpUtxoI } from "./interface";
|
|
16
|
-
import BigNumber from "bignumber.js";
|
|
17
|
-
|
|
18
|
-
test.skip("Test SLP genesis txo bytecode per SLP Spec", async () => {
|
|
19
|
-
const wallet = await RegTestWallet.newRandom();
|
|
20
|
-
|
|
21
|
-
const genesisOptions: SlpGenesisOptions = {
|
|
22
|
-
name: "Tether Ltd. US dollar backed tokens",
|
|
23
|
-
ticker: "USDT",
|
|
24
|
-
decimals: 8,
|
|
25
|
-
initialAmount: 100000000,
|
|
26
|
-
documentUrl:
|
|
27
|
-
"https://tether.to/wp-content/uploads/2016/06/TetherWhitePaper.pdf",
|
|
28
|
-
documentHash:
|
|
29
|
-
"db4451f11eda33950670aaf59e704da90117ff7057283b032cfaec7779313916",
|
|
30
|
-
tokenReceiverSlpAddr: wallet.slp.slpaddr,
|
|
31
|
-
batonReceiverSlpAddr: wallet.slp.slpaddr,
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const result = await SlpGetGenesisOutputs(genesisOptions);
|
|
35
|
-
const genesisTxoBytecode = result.SlpOutputs[0].lockingBytecode;
|
|
36
|
-
|
|
37
|
-
const hex = binToHex(genesisTxoBytecode);
|
|
38
|
-
expect(hex).toBe(
|
|
39
|
-
"6a04534c500001010747454e45534953045553445423546574686572204c74642e20555320646f6c6c6172206261636b656420746f6b656e734168747470733a2f2f7465746865722e746f2f77702d636f6e74656e742f75706c6f6164732f323031362f30362f546574686572576869746550617065722e70646620db4451f11eda33950670aaf59e704da90117ff7057283b032cfaec77793139160108010208002386f26fc10000"
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
parseSLP(Buffer.from(hex, "hex"));
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
test("Test SLP genesis txo bytecode with empty strings", async () => {
|
|
46
|
-
const wallet = await RegTestWallet.newRandom();
|
|
47
|
-
|
|
48
|
-
const genesisOptions: SlpGenesisOptions = {
|
|
49
|
-
name: "",
|
|
50
|
-
ticker: "",
|
|
51
|
-
decimals: 5,
|
|
52
|
-
initialAmount: 1000,
|
|
53
|
-
documentUrl: "",
|
|
54
|
-
documentHash: "",
|
|
55
|
-
tokenReceiverSlpAddr: wallet.slp.slpaddr,
|
|
56
|
-
batonReceiverSlpAddr: wallet.slp.slpaddr,
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const result = await SlpGetGenesisOutputs(genesisOptions);
|
|
60
|
-
const genesisTxoBytecode = result.SlpOutputs[0].lockingBytecode;
|
|
61
|
-
|
|
62
|
-
const hex = binToHex(genesisTxoBytecode);
|
|
63
|
-
expect(hex).toBe(
|
|
64
|
-
"6a04534c500001010747454e455349534c004c004c004c0001050102080000000005f5e100"
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
parseSLP(Buffer.from(hex, "hex"));
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test("Test SLP genesis txo bytecode with utf strings", async () => {
|
|
71
|
-
const wallet = await RegTestWallet.newRandom();
|
|
72
|
-
|
|
73
|
-
const genesisOptions: SlpGenesisOptions = {
|
|
74
|
-
name: "Music 🎵",
|
|
75
|
-
ticker: "🎵",
|
|
76
|
-
decimals: 0,
|
|
77
|
-
initialAmount: 100000,
|
|
78
|
-
documentUrl: "http://tiny.cc/gcmzcz",
|
|
79
|
-
documentHash: "",
|
|
80
|
-
tokenReceiverSlpAddr: wallet.slp.slpaddr,
|
|
81
|
-
batonReceiverSlpAddr: wallet.slp.slpaddr,
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const result = await SlpGetGenesisOutputs(genesisOptions);
|
|
85
|
-
const genesisTxoBytecode = result.SlpOutputs[0].lockingBytecode;
|
|
86
|
-
|
|
87
|
-
const hex = binToHex(genesisTxoBytecode);
|
|
88
|
-
expect(hex).toBe(
|
|
89
|
-
"6a04534c500001010747454e4553495304f09f8eb50a4d7573696320f09f8eb515687474703a2f2f74696e792e63632f67636d7a637a4c00010001020800000000000186a0"
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
parseSLP(Buffer.from(hex, "hex"));
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
test("Test SLP send txo bytecode per SLP Spec", async () => {
|
|
96
|
-
const wallet = await RegTestWallet.newRandom();
|
|
97
|
-
const fundingSlpUtxo: SlpUtxoI = {
|
|
98
|
-
value: new BigNumber(100000000),
|
|
99
|
-
decimals: 8,
|
|
100
|
-
txid: "",
|
|
101
|
-
vout: 1,
|
|
102
|
-
satoshis: DUST_UTXO_THRESHOLD,
|
|
103
|
-
ticker: "USDT",
|
|
104
|
-
tokenId: "550d19eb820e616a54b8a73372c4420b5a0567d8dc00f613b71c5234dc884b35",
|
|
105
|
-
type: SlpTokenType.Type1,
|
|
106
|
-
isBaton: false,
|
|
107
|
-
};
|
|
108
|
-
const sendRequest: SlpSendRequest = {
|
|
109
|
-
slpaddr: wallet.slp.slpaddr,
|
|
110
|
-
value: 1000000,
|
|
111
|
-
tokenId: "550d19eb820e616a54b8a73372c4420b5a0567d8dc00f613b71c5234dc884b35",
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
const result = await SlpGetSendOutputs(
|
|
115
|
-
wallet.slp.slpaddr,
|
|
116
|
-
[fundingSlpUtxo],
|
|
117
|
-
[sendRequest]
|
|
118
|
-
);
|
|
119
|
-
const sendTxoBytecode = result.SlpOutputs[0].lockingBytecode;
|
|
120
|
-
|
|
121
|
-
const hex = binToHex(sendTxoBytecode);
|
|
122
|
-
expect(hex).toBe(
|
|
123
|
-
"6a04534c500001010453454e4420550d19eb820e616a54b8a73372c4420b5a0567d8dc00f613b71c5234dc884b350800005af3107a40000800232bff5f46c000"
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
parseSLP(Buffer.from(hex, "hex"));
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
test("Test SLP mint txo bytecode per SLP Spec", async () => {
|
|
130
|
-
const wallet = await RegTestWallet.newRandom();
|
|
131
|
-
const batonSlpUtxo: SlpUtxoI = {
|
|
132
|
-
value: new BigNumber(100000000),
|
|
133
|
-
decimals: 8,
|
|
134
|
-
txid: "",
|
|
135
|
-
vout: 1,
|
|
136
|
-
satoshis: DUST_UTXO_THRESHOLD,
|
|
137
|
-
ticker: "USDT",
|
|
138
|
-
tokenId: "550d19eb820e616a54b8a73372c4420b5a0567d8dc00f613b71c5234dc884b35",
|
|
139
|
-
type: 0x01,
|
|
140
|
-
isBaton: false,
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
const result = await SlpGetMintOutputs(
|
|
144
|
-
{
|
|
145
|
-
tokenId:
|
|
146
|
-
"550d19eb820e616a54b8a73372c4420b5a0567d8dc00f613b71c5234dc884b35",
|
|
147
|
-
value: 100000000,
|
|
148
|
-
tokenReceiverSlpAddr: wallet.slp.slpaddr,
|
|
149
|
-
batonReceiverSlpAddr: wallet.slp.slpaddr,
|
|
150
|
-
endBaton: false,
|
|
151
|
-
},
|
|
152
|
-
[batonSlpUtxo]
|
|
153
|
-
);
|
|
154
|
-
const mintTxoBytecode = result.SlpOutputs[0].lockingBytecode;
|
|
155
|
-
|
|
156
|
-
const hex = binToHex(mintTxoBytecode);
|
|
157
|
-
expect(hex).toBe(
|
|
158
|
-
"6a04534c50000101044d494e5420550d19eb820e616a54b8a73372c4420b5a0567d8dc00f613b71c5234dc884b35010208002386f26fc10000"
|
|
159
|
-
);
|
|
160
|
-
|
|
161
|
-
parseSLP(Buffer.from(hex, "hex"));
|
|
162
|
-
});
|
package/src/slp/SlpLibAuth.ts
DELETED
|
@@ -1,532 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
authenticationTemplateToCompilerBCH,
|
|
3
|
-
bigIntToBinUint64LE,
|
|
4
|
-
binToHex,
|
|
5
|
-
hexToBin,
|
|
6
|
-
importAuthenticationTemplate,
|
|
7
|
-
Output,
|
|
8
|
-
utf8ToBin,
|
|
9
|
-
} from "@bitauth/libauth";
|
|
10
|
-
import { parseSLP } from "slp-parser";
|
|
11
|
-
|
|
12
|
-
import { SendRequest } from "../wallet/model.js";
|
|
13
|
-
import {
|
|
14
|
-
SlpGenesisOptions,
|
|
15
|
-
SlpMintOptions,
|
|
16
|
-
SlpSendRequest,
|
|
17
|
-
SlpTokenType,
|
|
18
|
-
SlpUtxoI,
|
|
19
|
-
} from "../slp/interface.js";
|
|
20
|
-
|
|
21
|
-
import BigNumber from "bignumber.js";
|
|
22
|
-
import { DUST_UTXO_THRESHOLD } from "../constant.js";
|
|
23
|
-
import { UnitEnum } from "../enum.js";
|
|
24
|
-
import { isValidAddress, toCashAddress } from "../util/bchaddr.js";
|
|
25
|
-
|
|
26
|
-
export const bigIntToBinUint64BE = (value) => {
|
|
27
|
-
return bigIntToBinUint64LE(value).reverse();
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const stringToBin = (value, hex = false) => {
|
|
31
|
-
if (!value) return Uint8Array.from([0x4c, 0x00]);
|
|
32
|
-
|
|
33
|
-
if (hex) return Uint8Array.from([...[value.length / 2], ...hexToBin(value)]);
|
|
34
|
-
|
|
35
|
-
const length = new TextEncoder().encode(value).length;
|
|
36
|
-
return Uint8Array.from([...[length], ...utf8ToBin(value)]);
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const supportedTokenTypes = [
|
|
40
|
-
SlpTokenType.Type1,
|
|
41
|
-
SlpTokenType.NftParent,
|
|
42
|
-
SlpTokenType.NftChild,
|
|
43
|
-
];
|
|
44
|
-
|
|
45
|
-
export const SlpGetGenesisOutputs = async (options: SlpGenesisOptions) => {
|
|
46
|
-
if (!isValidAddress(options.tokenReceiverSlpAddr!)) {
|
|
47
|
-
throw new Error(
|
|
48
|
-
`Invalid tokenReceiverSlpAddr ${options.tokenReceiverSlpAddr}`
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (!isValidAddress(options.batonReceiverSlpAddr!)) {
|
|
53
|
-
throw new Error(
|
|
54
|
-
`Invalid batonReceiverSlpAddr ${options.batonReceiverSlpAddr}`
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (!options.type) {
|
|
59
|
-
options.type = SlpTokenType.Type1;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (!supportedTokenTypes.includes(options.type)) {
|
|
63
|
-
throw new Error(`Unsupported token type ${options.type}`);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// explicitly convert initial amount to bignumber
|
|
67
|
-
options.initialAmount = new BigNumber(options.initialAmount);
|
|
68
|
-
if (options.initialAmount.isLessThanOrEqualTo(0)) {
|
|
69
|
-
throw Error("Initial genesis token amount should be greater than zero");
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (options.decimals < 0 || options.decimals > 9) {
|
|
73
|
-
throw new Error("Genesis allows decimal places between 0");
|
|
74
|
-
}
|
|
75
|
-
const addrs = options.endBaton
|
|
76
|
-
? [options.tokenReceiverSlpAddr]
|
|
77
|
-
: [options.tokenReceiverSlpAddr, options.batonReceiverSlpAddr];
|
|
78
|
-
const bchSendRequests = addrs.map(
|
|
79
|
-
(val) =>
|
|
80
|
-
new SendRequest({
|
|
81
|
-
cashaddr: toCashAddress(val!),
|
|
82
|
-
value: DUST_UTXO_THRESHOLD,
|
|
83
|
-
unit: UnitEnum.SAT,
|
|
84
|
-
})
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
const template = importAuthenticationTemplate(SlpTxoTemplate);
|
|
88
|
-
if (typeof template === "string") {
|
|
89
|
-
throw new Error("Transaction template error");
|
|
90
|
-
}
|
|
91
|
-
const compiler = await authenticationTemplateToCompilerBCH(template);
|
|
92
|
-
|
|
93
|
-
const rawTokenAmount = BigInt(
|
|
94
|
-
options.initialAmount.shiftedBy(options.decimals)
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
const batonVout = options.endBaton ? [0x4c, 0x00] : [0x01, 0x02];
|
|
98
|
-
|
|
99
|
-
let genesisTxoBytecode = compiler.generateBytecode({
|
|
100
|
-
scriptId: "genesis_lock",
|
|
101
|
-
data: {
|
|
102
|
-
bytecode: {
|
|
103
|
-
g_token_type: Uint8Array.from([...[0x01], ...[options.type]]),
|
|
104
|
-
g_token_ticker: stringToBin(options.ticker),
|
|
105
|
-
g_token_name: stringToBin(options.name),
|
|
106
|
-
g_token_document_url: stringToBin(options.documentUrl),
|
|
107
|
-
g_token_document_hash: stringToBin(options.documentHash, true),
|
|
108
|
-
g_decimals: Uint8Array.from([...[0x01], ...[options.decimals]]),
|
|
109
|
-
g_mint_baton_vout: Uint8Array.from(batonVout),
|
|
110
|
-
g_initial_token_mint_quantity: Uint8Array.from([
|
|
111
|
-
...[0x08],
|
|
112
|
-
...bigIntToBinUint64BE(rawTokenAmount),
|
|
113
|
-
]),
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
});
|
|
117
|
-
if (!genesisTxoBytecode.success) {
|
|
118
|
-
throw new Error(genesisTxoBytecode.errors.map((e) => e.error).join("\n"));
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
SlpOutputs: [
|
|
123
|
-
{
|
|
124
|
-
lockingBytecode: genesisTxoBytecode.bytecode,
|
|
125
|
-
valueSatoshis: 0n,
|
|
126
|
-
} as Output,
|
|
127
|
-
],
|
|
128
|
-
FundingSlpUtxos: [],
|
|
129
|
-
BchSendRequests: bchSendRequests,
|
|
130
|
-
};
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
export const SlpGetMintOutputs = async (
|
|
134
|
-
options: SlpMintOptions,
|
|
135
|
-
slpBatonUtxos: SlpUtxoI[]
|
|
136
|
-
) => {
|
|
137
|
-
if (!isValidAddress(options.tokenReceiverSlpAddr!)) {
|
|
138
|
-
throw new Error(
|
|
139
|
-
`Invalid tokenReceiverSlpAddr ${options.tokenReceiverSlpAddr}`
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (!isValidAddress(options.batonReceiverSlpAddr!)) {
|
|
144
|
-
throw new Error(
|
|
145
|
-
`Invalid batonReceiverSlpAddr ${options.batonReceiverSlpAddr}`
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const tokenType = slpBatonUtxos[0].type;
|
|
150
|
-
|
|
151
|
-
if (!supportedTokenTypes.includes(tokenType)) {
|
|
152
|
-
throw new Error(`Unsupported token type ${tokenType}`);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const addrs = options.endBaton
|
|
156
|
-
? [options.tokenReceiverSlpAddr]
|
|
157
|
-
: [options.tokenReceiverSlpAddr, options.batonReceiverSlpAddr];
|
|
158
|
-
const bchSendRequests = addrs.map(
|
|
159
|
-
(val) =>
|
|
160
|
-
new SendRequest({
|
|
161
|
-
cashaddr: toCashAddress(val!),
|
|
162
|
-
value: DUST_UTXO_THRESHOLD,
|
|
163
|
-
unit: UnitEnum.SAT,
|
|
164
|
-
})
|
|
165
|
-
);
|
|
166
|
-
|
|
167
|
-
const template = importAuthenticationTemplate(SlpTxoTemplate);
|
|
168
|
-
if (typeof template === "string") {
|
|
169
|
-
throw new Error("Transaction template error");
|
|
170
|
-
}
|
|
171
|
-
const compiler = await authenticationTemplateToCompilerBCH(template);
|
|
172
|
-
const decimals = slpBatonUtxos[0].decimals;
|
|
173
|
-
const amount = new BigNumber(options.value).shiftedBy(decimals);
|
|
174
|
-
|
|
175
|
-
const batonVout = options.endBaton ? [0x4c, 0x00] : [0x01, 0x02];
|
|
176
|
-
|
|
177
|
-
let mintTxoBytecode = compiler.generateBytecode({
|
|
178
|
-
scriptId: "mint_lock",
|
|
179
|
-
data: {
|
|
180
|
-
bytecode: {
|
|
181
|
-
m_token_type: Uint8Array.from([...[0x01], ...[tokenType]]),
|
|
182
|
-
m_token_id: hexToBin(options.tokenId),
|
|
183
|
-
m_mint_baton_vout: Uint8Array.from(batonVout),
|
|
184
|
-
m_additional_token_quantity: Uint8Array.from([
|
|
185
|
-
...[0x08],
|
|
186
|
-
...bigIntToBinUint64BE(BigInt(amount.toString())),
|
|
187
|
-
]),
|
|
188
|
-
},
|
|
189
|
-
},
|
|
190
|
-
});
|
|
191
|
-
if (!mintTxoBytecode.success) {
|
|
192
|
-
throw new Error(mintTxoBytecode.errors.map((e) => e.error).join("\n"));
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
return {
|
|
196
|
-
SlpOutputs: [
|
|
197
|
-
{
|
|
198
|
-
lockingBytecode: mintTxoBytecode.bytecode,
|
|
199
|
-
valueSatoshis: 0n,
|
|
200
|
-
} as Output,
|
|
201
|
-
],
|
|
202
|
-
FundingSlpUtxos: slpBatonUtxos,
|
|
203
|
-
BchSendRequests: bchSendRequests,
|
|
204
|
-
};
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
export const SlpGetSendOutputs = async (
|
|
208
|
-
changeSlpaddr: string,
|
|
209
|
-
slpUtxos: SlpUtxoI[],
|
|
210
|
-
sendRequests: SlpSendRequest[]
|
|
211
|
-
) => {
|
|
212
|
-
if (!isValidAddress(changeSlpaddr!)) {
|
|
213
|
-
throw new Error(`Invalid changeSlpaddr ${changeSlpaddr}`);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (!slpUtxos.length) {
|
|
217
|
-
throw new Error("No available tokens to spend");
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
const decimals = slpUtxos[0].decimals;
|
|
221
|
-
const tokenId = slpUtxos[0].tokenId;
|
|
222
|
-
const tokenType = slpUtxos[0].type;
|
|
223
|
-
|
|
224
|
-
if (!supportedTokenTypes.includes(tokenType)) {
|
|
225
|
-
throw new Error(`Unsupported token type ${tokenType}`);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// sort inputs in ascending order to eliminate the unnecessary splitting
|
|
229
|
-
// and to prefer the consolidation of small inputs
|
|
230
|
-
slpUtxos = slpUtxos.sort((a, b) => a.value.comparedTo(b.value));
|
|
231
|
-
|
|
232
|
-
const slpAvailableAmount: BigNumber = slpUtxos
|
|
233
|
-
.map((val) => new BigNumber(val.value))
|
|
234
|
-
.reduce((a, b) => BigNumber.sum(a, b), new BigNumber(0));
|
|
235
|
-
const slpSpendAmount: BigNumber = sendRequests
|
|
236
|
-
.map((val) => new BigNumber(val.value))
|
|
237
|
-
.reduce((a, b) => BigNumber.sum(a, b), new BigNumber(0));
|
|
238
|
-
|
|
239
|
-
if (slpSpendAmount.isLessThanOrEqualTo(0)) {
|
|
240
|
-
throw new Error("Refusing to spend 0 tokens");
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
if (slpSpendAmount.isGreaterThan(slpAvailableAmount)) {
|
|
244
|
-
throw new Error("Not enough tokens to spend");
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
let fundingSlpUtxos: SlpUtxoI[] = [];
|
|
248
|
-
let totalInputTokens = new BigNumber(0);
|
|
249
|
-
for (let slputxo of slpUtxos) {
|
|
250
|
-
const amountTooLow = totalInputTokens.isLessThan(slpSpendAmount);
|
|
251
|
-
if (amountTooLow) {
|
|
252
|
-
totalInputTokens = totalInputTokens.plus(slputxo.value);
|
|
253
|
-
fundingSlpUtxos.push(slputxo);
|
|
254
|
-
} else {
|
|
255
|
-
break;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
const template = importAuthenticationTemplate(SlpTxoTemplate);
|
|
260
|
-
if (typeof template === "string") {
|
|
261
|
-
throw new Error("Transaction template error");
|
|
262
|
-
}
|
|
263
|
-
const compiler = await authenticationTemplateToCompilerBCH(template);
|
|
264
|
-
|
|
265
|
-
const change = totalInputTokens.minus(slpSpendAmount);
|
|
266
|
-
let values = sendRequests.map((val) => new BigNumber(val.value));
|
|
267
|
-
if (change.isGreaterThan(new BigNumber(0))) {
|
|
268
|
-
values.push(change);
|
|
269
|
-
sendRequests.push({
|
|
270
|
-
slpaddr: changeSlpaddr,
|
|
271
|
-
tokenId: tokenId,
|
|
272
|
-
value: new BigNumber(0),
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
const bchSendRequests = sendRequests.map(
|
|
277
|
-
(val) =>
|
|
278
|
-
new SendRequest({
|
|
279
|
-
cashaddr: toCashAddress(val.slpaddr),
|
|
280
|
-
value: DUST_UTXO_THRESHOLD,
|
|
281
|
-
unit: UnitEnum.SAT,
|
|
282
|
-
})
|
|
283
|
-
);
|
|
284
|
-
|
|
285
|
-
values = values.map((val) => val.shiftedBy(decimals));
|
|
286
|
-
|
|
287
|
-
let result: Uint8Array = new Uint8Array();
|
|
288
|
-
for (const val of values) {
|
|
289
|
-
result = new Uint8Array([
|
|
290
|
-
...result,
|
|
291
|
-
...[0x08],
|
|
292
|
-
...bigIntToBinUint64BE(BigInt(val.toString())),
|
|
293
|
-
]);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
let sendTxoBytecode = compiler.generateBytecode({
|
|
297
|
-
scriptId: "send_lock",
|
|
298
|
-
data: {
|
|
299
|
-
bytecode: {
|
|
300
|
-
s_token_type: Uint8Array.from([...[0x01], ...[tokenType]]),
|
|
301
|
-
s_token_id: hexToBin(tokenId!),
|
|
302
|
-
s_token_output_quantities: result,
|
|
303
|
-
},
|
|
304
|
-
},
|
|
305
|
-
});
|
|
306
|
-
if (!sendTxoBytecode.success) {
|
|
307
|
-
throw new Error(sendTxoBytecode.errors.map((e) => e.error).join("\n"));
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// enforce checking
|
|
311
|
-
parseSLP(Buffer.from(binToHex(sendTxoBytecode.bytecode), "hex"));
|
|
312
|
-
|
|
313
|
-
return {
|
|
314
|
-
SlpOutputs: [
|
|
315
|
-
{
|
|
316
|
-
lockingBytecode: sendTxoBytecode.bytecode,
|
|
317
|
-
valueSatoshis: 0n,
|
|
318
|
-
} as Output,
|
|
319
|
-
],
|
|
320
|
-
FundingSlpUtxos: fundingSlpUtxos,
|
|
321
|
-
BchSendRequests: bchSendRequests,
|
|
322
|
-
};
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
// prettier-ignore
|
|
326
|
-
export const SlpTxoTemplate = {
|
|
327
|
-
"$schema": "https://bitauth.com/schemas/authentication-template-v0.schema.json",
|
|
328
|
-
"description": "SLP Token transaction output templates",
|
|
329
|
-
"name": "SLP",
|
|
330
|
-
"entities": {
|
|
331
|
-
"genesis_variables": {
|
|
332
|
-
"description": "Variables used in genesis template.",
|
|
333
|
-
"name": "Genesis_Variables",
|
|
334
|
-
"scripts": [
|
|
335
|
-
"genesis_lock",
|
|
336
|
-
"genesis_unlock"
|
|
337
|
-
],
|
|
338
|
-
"variables": {
|
|
339
|
-
"g_token_type": {
|
|
340
|
-
"description": "1 to 2 byte integer",
|
|
341
|
-
"name": "token_type",
|
|
342
|
-
"type": "AddressData"
|
|
343
|
-
},
|
|
344
|
-
"g_token_ticker": {
|
|
345
|
-
"description": "0 to ∞ bytes, suggested utf-8",
|
|
346
|
-
"name": "token_ticker",
|
|
347
|
-
"type": "AddressData"
|
|
348
|
-
},
|
|
349
|
-
"g_token_name": {
|
|
350
|
-
"description": "0 to ∞ bytes, suggested utf-8",
|
|
351
|
-
"name": "token_name",
|
|
352
|
-
"type": "AddressData"
|
|
353
|
-
},
|
|
354
|
-
"g_token_document_url": {
|
|
355
|
-
"description": "0 to ∞ bytes, suggested ascii",
|
|
356
|
-
"name": "token_document_url",
|
|
357
|
-
"type": "AddressData"
|
|
358
|
-
},
|
|
359
|
-
"g_token_document_hash": {
|
|
360
|
-
"description": "0 bytes or 32 bytes",
|
|
361
|
-
"name": "token_document_hash",
|
|
362
|
-
"type": "AddressData"
|
|
363
|
-
},
|
|
364
|
-
"g_decimals": {
|
|
365
|
-
"description": "1 byte in range 0x00-0x09",
|
|
366
|
-
"name": "decimals",
|
|
367
|
-
"type": "AddressData"
|
|
368
|
-
},
|
|
369
|
-
"g_mint_baton_vout": {
|
|
370
|
-
"description": "0 bytes, or 1 byte in range 0x02-0xff",
|
|
371
|
-
"name": "mint_baton_vout",
|
|
372
|
-
"type": "AddressData"
|
|
373
|
-
},
|
|
374
|
-
"g_initial_token_mint_quantity": {
|
|
375
|
-
"description": "8 byte integer",
|
|
376
|
-
"name": "initial_token_mint_quantity",
|
|
377
|
-
"type": "AddressData"
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
},
|
|
381
|
-
"send_variables": {
|
|
382
|
-
"description": "",
|
|
383
|
-
"name": "Send_Variables",
|
|
384
|
-
"scripts": [
|
|
385
|
-
"send_lock",
|
|
386
|
-
"send_unlock"
|
|
387
|
-
],
|
|
388
|
-
"variables": {
|
|
389
|
-
"s_token_type": {
|
|
390
|
-
"description": "1 to 2 byte integer",
|
|
391
|
-
"name": "token_type",
|
|
392
|
-
"type": "AddressData"
|
|
393
|
-
},
|
|
394
|
-
"s_token_id": {
|
|
395
|
-
"description": "Token Id, genesis transaction hex",
|
|
396
|
-
"name": "Token_Id",
|
|
397
|
-
"type": "AddressData"
|
|
398
|
-
},
|
|
399
|
-
"s_token_output_quantities": {
|
|
400
|
-
"description": "N 8 byte integer token amounts (up to 19). At least one is required. Each one is a push.\nN BCH transaction outputs should be specified",
|
|
401
|
-
"name": "Token Output Quantities",
|
|
402
|
-
"type": "AddressData"
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
},
|
|
406
|
-
"mint_variables": {
|
|
407
|
-
"description": "",
|
|
408
|
-
"name": "Mint_Variables",
|
|
409
|
-
"scripts": [
|
|
410
|
-
"mint_lock",
|
|
411
|
-
"mint_unlock"
|
|
412
|
-
],
|
|
413
|
-
"variables": {
|
|
414
|
-
"m_token_type": {
|
|
415
|
-
"description": "1 to 2 byte integer",
|
|
416
|
-
"name": "token_type",
|
|
417
|
-
"type": "AddressData"
|
|
418
|
-
},
|
|
419
|
-
"m_token_id": {
|
|
420
|
-
"description": "Token Id, genesis transaction hex",
|
|
421
|
-
"name": "Token_Id",
|
|
422
|
-
"type": "AddressData"
|
|
423
|
-
},
|
|
424
|
-
"m_mint_baton_vout": {
|
|
425
|
-
"description": "0 bytes, or 1 byte in range 0x02-0xff",
|
|
426
|
-
"name": "mint_baton_vout",
|
|
427
|
-
"type": "AddressData"
|
|
428
|
-
},
|
|
429
|
-
"m_additional_token_quantity": {
|
|
430
|
-
"description": "Amount of tokens to mint, 8 byte integer",
|
|
431
|
-
"name": "Additinial token quantity",
|
|
432
|
-
"type": "AddressData"
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
},
|
|
437
|
-
"scenarios": {
|
|
438
|
-
"genesis": {
|
|
439
|
-
"data": {
|
|
440
|
-
"bytecode": {
|
|
441
|
-
"g_token_type": "0x01",
|
|
442
|
-
"g_token_ticker": "0x00",
|
|
443
|
-
"g_token_name": "0x00",
|
|
444
|
-
"g_token_document_url": "0x00",
|
|
445
|
-
"g_token_document_hash": "",
|
|
446
|
-
"g_decimals": "0x09",
|
|
447
|
-
"g_mint_baton_vout": "0x02",
|
|
448
|
-
"g_initial_token_mint_quantity": "0x0102030405060708"
|
|
449
|
-
}
|
|
450
|
-
},
|
|
451
|
-
"description": "Genesis",
|
|
452
|
-
"name": "Genesis",
|
|
453
|
-
"transaction": {
|
|
454
|
-
"locktime": 100
|
|
455
|
-
}
|
|
456
|
-
},
|
|
457
|
-
"send": {
|
|
458
|
-
"data": {
|
|
459
|
-
"bytecode": {
|
|
460
|
-
"s_token_type": "0x01",
|
|
461
|
-
"s_token_id": "0x0000000000000000'0000000000000000'0000000000000000'0000000000000000'",
|
|
462
|
-
"s_token_output_quantities": "0x0000000000000000"
|
|
463
|
-
}
|
|
464
|
-
},
|
|
465
|
-
"description": "Send",
|
|
466
|
-
"name": "Send",
|
|
467
|
-
"transaction": {
|
|
468
|
-
"locktime": 100
|
|
469
|
-
}
|
|
470
|
-
},
|
|
471
|
-
"mint": {
|
|
472
|
-
"data": {
|
|
473
|
-
"bytecode": {
|
|
474
|
-
"m_token_type": "0x01",
|
|
475
|
-
"m_token_id": "0x0000000000000000'0000000000000000'0000000000000000'0000000000000000'",
|
|
476
|
-
"m_mint_baton_vout": "0x00",
|
|
477
|
-
"m_additional_token_quantity": "0x0000000000000000"
|
|
478
|
-
}
|
|
479
|
-
},
|
|
480
|
-
"description": "Mint",
|
|
481
|
-
"name": "Mint",
|
|
482
|
-
"transaction": {
|
|
483
|
-
"locktime": 100
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
},
|
|
487
|
-
"scripts": {
|
|
488
|
-
"genesis_unlock": {
|
|
489
|
-
"fails": [
|
|
490
|
-
"genesis"
|
|
491
|
-
],
|
|
492
|
-
"name": "Genesis Unlock",
|
|
493
|
-
"script": "// unlock script is required, so we leave it empty",
|
|
494
|
-
"unlocks": "genesis_lock"
|
|
495
|
-
},
|
|
496
|
-
"send_unlock": {
|
|
497
|
-
"fails": [
|
|
498
|
-
"send"
|
|
499
|
-
],
|
|
500
|
-
"name": "Send Unlock",
|
|
501
|
-
"script": "",
|
|
502
|
-
"unlocks": "send_lock"
|
|
503
|
-
},
|
|
504
|
-
"mint_unlock": {
|
|
505
|
-
"fails": [
|
|
506
|
-
"mint"
|
|
507
|
-
],
|
|
508
|
-
"name": "Mint Unlock",
|
|
509
|
-
"script": "",
|
|
510
|
-
"unlocks": "mint_lock"
|
|
511
|
-
},
|
|
512
|
-
"genesis_lock": {
|
|
513
|
-
"lockingType": "standard",
|
|
514
|
-
"name": "Genesis",
|
|
515
|
-
"script": "OP_RETURN <'SLP'0x00> g_token_type <'GENESIS'> g_token_ticker g_token_name g_token_document_url g_token_document_hash g_decimals g_mint_baton_vout g_initial_token_mint_quantity"
|
|
516
|
-
},
|
|
517
|
-
"send_lock": {
|
|
518
|
-
"lockingType": "standard",
|
|
519
|
-
"name": "Send",
|
|
520
|
-
"script": "OP_RETURN <'SLP'0x00> s_token_type <'SEND'> <s_token_id> s_token_output_quantities"
|
|
521
|
-
},
|
|
522
|
-
"mint_lock": {
|
|
523
|
-
"lockingType": "standard",
|
|
524
|
-
"name": "Mint",
|
|
525
|
-
"script": "OP_RETURN <'SLP'0x00> m_token_type <'MINT'> <m_token_id> m_mint_baton_vout m_additional_token_quantity"
|
|
526
|
-
}
|
|
527
|
-
},
|
|
528
|
-
"supported": [
|
|
529
|
-
"BCH_2020_05"
|
|
530
|
-
],
|
|
531
|
-
"version": 0
|
|
532
|
-
}
|