Skip to content

Commit 27be3c8

Browse files
committed
docs(root): refactor omni_example to index and debugging.ts
BTC-1864 TICKET: BTC-0
1 parent 7d58085 commit 27be3c8

File tree

3 files changed

+80
-65
lines changed

3 files changed

+80
-65
lines changed

examples/ts/btc/omni/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,6 @@ export const omniConfig = {
2323
walletPassphrase,
2424
walletId,
2525
otp,
26+
MEMPOOL_PREFIX: env === 'test' ? 'testnet4/' : '',
27+
OMNI_PREFIX: Buffer.from('6f6d6e69', 'hex'),
2628
};

examples/ts/btc/omni/debugging.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { Wallet } from '@bitgo/sdk-core';
2+
import * as superagent from 'superagent';
3+
import * as utxolib from '@bitgo/utxo-lib';
4+
import { omniConfig } from './config';
5+
6+
export async function mintOmniAsset(wallet: Wallet, address: string, feeRate = 20_000): Promise<void> {
7+
const transactionVersion = Buffer.alloc(2);
8+
const transactionType = Buffer.alloc(2);
9+
transactionType.writeUint16BE(50);
10+
const ecoSystem = Buffer.alloc(1);
11+
ecoSystem.writeInt8(2);
12+
const propertyType = Buffer.alloc(2);
13+
propertyType.writeUint16BE(2);
14+
const previousPropertyID = Buffer.alloc(4);
15+
16+
const category = Buffer.from('Other\0');
17+
const subCategory = Buffer.from('Other\0');
18+
const propertyTitle = Buffer.from('Testcoin\0');
19+
const propertyURL = Buffer.from('https://example.com\0');
20+
const propertyData = Buffer.from('\0');
21+
22+
const amount = Buffer.alloc(8);
23+
amount.writeBigUint64BE(BigInt(100000 * 10 ** 8));
24+
25+
const res = await superagent.get(`https://mempool.space/${omniConfig.MEMPOOL_PREFIX}api/address/${address}/utxo`);
26+
const unspent = res.body[0];
27+
const unspent_id = unspent.txid + ':' + unspent.vout;
28+
29+
const omniScript = Buffer.concat([
30+
omniConfig.OMNI_PREFIX, // omni
31+
transactionVersion,
32+
transactionType,
33+
ecoSystem,
34+
propertyType,
35+
previousPropertyID,
36+
category,
37+
subCategory,
38+
propertyTitle,
39+
propertyURL,
40+
propertyData,
41+
amount,
42+
]);
43+
44+
const output = utxolib.payments.embed({ data: [omniScript], network: utxolib.networks.bitcoin }).output;
45+
if (!output) {
46+
throw new Error('Invalid output');
47+
}
48+
const script = output.toString('hex');
49+
const tx = await wallet.sendMany({
50+
recipients: [
51+
{
52+
amount: '0',
53+
address: `scriptPubkey:${script}`,
54+
},
55+
],
56+
isReplaceableByFee: true,
57+
feeRate,
58+
walletPassphrase: omniConfig.walletPassphrase,
59+
changeAddress: address,
60+
unspents: [unspent_id],
61+
});
62+
console.log('Omni asset created: ', tx);
63+
}

examples/ts/btc/omni/index.ts

Lines changed: 15 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -10,75 +10,13 @@ import * as utxolib from '@bitgo/utxo-lib';
1010

1111
const RECEIVE_ADDRESS = '';
1212
const SEND_ADDRESS = '';
13-
const MEMPOOL_PREFIX = omniConfig.coin === 'tbtc4' ? 'testnet4/' : '';
1413
const AMOUNT = 729100000n;
1514
const ASSET_ID = 31;
16-
const OMNI_PREFIX = Buffer.from('6f6d6e69', 'hex');
1715

1816
async function getWallet() {
1917
return await omniConfig.sdk.coin(omniConfig.coin).wallets().get({ id: omniConfig.walletId });
2018
}
2119

22-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
23-
async function mintOmniAsset(wallet: Wallet, address: string, feeRate = 20_000) {
24-
const transactionVersion = Buffer.alloc(2);
25-
const transactionType = Buffer.alloc(2);
26-
transactionType.writeUint16BE(50);
27-
const ecoSystem = Buffer.alloc(1);
28-
ecoSystem.writeInt8(2);
29-
const propertyType = Buffer.alloc(2);
30-
propertyType.writeUint16BE(2);
31-
const previousPropertyID = Buffer.alloc(4);
32-
33-
const category = Buffer.from('Other\0');
34-
const subCategory = Buffer.from('Other\0');
35-
const propertyTitle = Buffer.from('Testcoin\0');
36-
const propertyURL = Buffer.from('https://example.com\0');
37-
const propertyData = Buffer.from('\0');
38-
39-
const amount = Buffer.alloc(8);
40-
amount.writeBigUint64BE(BigInt(100000 * 10 ** 8));
41-
42-
const res = await superagent.get(`https://mempool.space/${MEMPOOL_PREFIX}api/address/${address}/utxo`);
43-
const unspent = res.body[0];
44-
const unspent_id = unspent.txid + ':' + unspent.vout;
45-
46-
const omniScript = Buffer.concat([
47-
OMNI_PREFIX, // omni
48-
transactionVersion,
49-
transactionType,
50-
ecoSystem,
51-
propertyType,
52-
previousPropertyID,
53-
category,
54-
subCategory,
55-
propertyTitle,
56-
propertyURL,
57-
propertyData,
58-
amount,
59-
]);
60-
61-
const output = utxolib.payments.embed({ data: [omniScript], network: utxolib.networks.bitcoin }).output;
62-
if (!output) {
63-
throw new Error('Invalid output');
64-
}
65-
const script = output.toString('hex');
66-
const tx = await wallet.sendMany({
67-
recipients: [
68-
{
69-
amount: '0',
70-
address: `scriptPubkey:${script}`,
71-
},
72-
],
73-
isReplaceableByFee: true,
74-
feeRate,
75-
walletPassphrase: omniConfig.walletPassphrase,
76-
changeAddress: address,
77-
unspents: [unspent_id],
78-
});
79-
console.log('Omni asset created: ', tx);
80-
}
81-
8220
async function sendOmniAsset(
8321
wallet: Wallet,
8422
receiver: string,
@@ -87,7 +25,13 @@ async function sendOmniAsset(
8725
assetId = 31,
8826
feeRate = 20_000
8927
) {
90-
const res = await superagent.get(`https://mempool.space/${MEMPOOL_PREFIX}/api/address/${sender}/utxo`);
28+
if (!['1', 'n', 'm'].includes(receiver.slice(0, 1))) {
29+
throw new Error(
30+
'Omni has only been verified to work with legacy addresses - use other address formats at your own risk'
31+
);
32+
}
33+
34+
const res = await superagent.get(`https://mempool.space/${omniConfig.MEMPOOL_PREFIX}api/address/${sender}/utxo`);
9135
const unspent = res.body[0];
9236
const unspent_id = unspent.txid + ':' + unspent.vout;
9337

@@ -97,18 +41,22 @@ async function sendOmniAsset(
9741
assetHex.writeUInt32BE(assetId);
9842
const amountHex = Buffer.alloc(8);
9943
amountHex.writeBigUInt64BE(amountMicroCents);
100-
const omniScript = Buffer.concat([OMNI_PREFIX, transactionType, assetHex, amountHex]);
44+
const omniScript = Buffer.concat([omniConfig.OMNI_PREFIX, transactionType, assetHex, amountHex]);
10145
const output = utxolib.payments.embed({ data: [omniScript], network: omniConfig.network }).output;
10246
if (!output) {
10347
throw new Error('Invalid output');
10448
}
10549
const script = output.toString('hex');
10650
const tx = await wallet.sendMany({
10751
recipients: [
52+
// this signals the receiver of the omni asset
53+
// we are not actually trying to send BTC to the receiver
54+
// so we send the minimum amount above the dust limit
10855
{
10956
amount: '546',
11057
address: receiver,
11158
},
59+
// this is the actual script that the omni layer reads for the send
11260
{
11361
amount: '0',
11462
address: `scriptPubkey:${script}`,
@@ -117,6 +65,8 @@ async function sendOmniAsset(
11765
isReplaceableByFee: true,
11866
feeRate,
11967
walletPassphrase: omniConfig.walletPassphrase,
68+
// we must send change to our input address to ensure that omni won't
69+
// accidentally send our asset to the change address instead of the recipient
12070
changeAddress: sender,
12171
unspents: [unspent_id],
12272
});
@@ -129,7 +79,7 @@ async function sendOmniAsset(
12979
async function main() {
13080
console.log('Starting...');
13181

132-
const feeRateRes = await superagent.get(`https://mempool.space/${MEMPOOL_PREFIX}api/v1/fees/recommended`);
82+
const feeRateRes = await superagent.get(`https://mempool.space/${omniConfig.MEMPOOL_PREFIX}api/v1/fees/recommended`);
13383
const feeRate = feeRateRes.body.fastestFee;
13484

13585
const wallet = await getWallet();

0 commit comments

Comments
 (0)