Skip to content

Commit 36dd950

Browse files
committed
feat: add p-chain etna examples
1 parent afa2f2d commit 36dd950

File tree

8 files changed

+266
-2
lines changed

8 files changed

+266
-2
lines changed

examples/p-chain/etna/base.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { TransferableOutput, addTxSignatures, pvm, utils } from '../../../src';
2+
import { getEnvVars } from '../../utils/getEnvVars';
3+
import { getEtnaContextFromURI } from './utils/etna-context';
4+
5+
/**
6+
* The amount of AVAX to send to self.
7+
*/
8+
const SEND_AVAX_AMOUNT: number = 0.001;
9+
10+
const main = async () => {
11+
const { AVAX_PUBLIC_URL, P_CHAIN_ADDRESS, PRIVATE_KEY } = getEnvVars();
12+
13+
const pvmApi = new pvm.PVMApi(AVAX_PUBLIC_URL);
14+
15+
const context = await getEtnaContextFromURI(AVAX_PUBLIC_URL);
16+
17+
const { utxos } = await pvmApi.getUTXOs({ addresses: [P_CHAIN_ADDRESS] });
18+
19+
const tx = pvm.e.newBaseTx(
20+
{
21+
fromAddressesBytes: [utils.bech32ToBytes(P_CHAIN_ADDRESS)],
22+
outputs: [
23+
TransferableOutput.fromNative(
24+
context.avaxAssetID,
25+
BigInt(SEND_AVAX_AMOUNT * 1e9),
26+
[utils.bech32ToBytes(P_CHAIN_ADDRESS)],
27+
),
28+
],
29+
utxos,
30+
},
31+
context,
32+
);
33+
34+
await addTxSignatures({
35+
unsignedTx: tx,
36+
privateKeys: [utils.hexToBuffer(PRIVATE_KEY)],
37+
});
38+
39+
return pvmApi.issueSignedTx(tx.getSignedTx());
40+
};
41+
42+
main().then(console.log);

examples/p-chain/etna/delegate.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { addTxSignatures, networkIDs, pvm, utils } from '../../../src';
2+
import { getEnvVars } from '../../utils/getEnvVars';
3+
import { getEtnaContextFromURI } from './utils/etna-context';
4+
5+
const AMOUNT_TO_DELEGATE_AVAX: number = 1;
6+
const DAYS_TO_DELEGATE: number = 21;
7+
8+
const main = async () => {
9+
const { AVAX_PUBLIC_URL, P_CHAIN_ADDRESS, PRIVATE_KEY } = getEnvVars();
10+
11+
const pvmApi = new pvm.PVMApi(AVAX_PUBLIC_URL);
12+
13+
const context = await getEtnaContextFromURI(AVAX_PUBLIC_URL);
14+
15+
const { utxos } = await pvmApi.getUTXOs({ addresses: [P_CHAIN_ADDRESS] });
16+
17+
const startTime = await pvmApi.getTimestamp();
18+
const startDate = new Date(startTime.timestamp);
19+
const start: bigint = BigInt(startDate.getTime() / 1_000);
20+
21+
const endTime = new Date(startTime.timestamp);
22+
endTime.setDate(endTime.getDate() + DAYS_TO_DELEGATE);
23+
const end: bigint = BigInt(endTime.getTime() / 1_000);
24+
25+
const nodeId = 'NodeID-HKLp5269LH8DcrLvHPc2PHjGczBQD3td4';
26+
27+
const tx = pvm.e.newAddPermissionlessDelegatorTx(
28+
{
29+
end,
30+
fromAddressesBytes: [utils.bech32ToBytes(P_CHAIN_ADDRESS)],
31+
nodeId,
32+
rewardAddresses: [utils.bech32ToBytes(P_CHAIN_ADDRESS)],
33+
start,
34+
subnetId: networkIDs.PrimaryNetworkID.toString(),
35+
utxos,
36+
weight: BigInt(AMOUNT_TO_DELEGATE_AVAX * 1e9),
37+
},
38+
context,
39+
);
40+
41+
await addTxSignatures({
42+
unsignedTx: tx,
43+
privateKeys: [utils.hexToBuffer(PRIVATE_KEY)],
44+
});
45+
46+
return pvmApi.issueSignedTx(tx.getSignedTx());
47+
};
48+
49+
main().then(console.log);

examples/p-chain/etna/export.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { TransferableOutput, addTxSignatures, pvm, utils } from '../../../src';
2+
import { getEnvVars } from '../../utils/getEnvVars';
3+
import { getEtnaContextFromURI } from './utils/etna-context';
4+
5+
const AMOUNT_TO_EXPORT_AVAX: number = 0.001;
6+
7+
const main = async () => {
8+
const { AVAX_PUBLIC_URL, P_CHAIN_ADDRESS, PRIVATE_KEY, X_CHAIN_ADDRESS } =
9+
getEnvVars();
10+
11+
const context = await getEtnaContextFromURI(AVAX_PUBLIC_URL);
12+
13+
const pvmApi = new pvm.PVMApi(AVAX_PUBLIC_URL);
14+
15+
const { utxos } = await pvmApi.getUTXOs({
16+
addresses: [P_CHAIN_ADDRESS],
17+
});
18+
19+
const exportTx = pvm.e.newExportTx(
20+
{
21+
destinationChainId: context.xBlockchainID,
22+
fromAddressesBytes: [utils.bech32ToBytes(P_CHAIN_ADDRESS)],
23+
outputs: [
24+
TransferableOutput.fromNative(
25+
context.avaxAssetID,
26+
BigInt(AMOUNT_TO_EXPORT_AVAX * 1e9),
27+
[utils.bech32ToBytes(X_CHAIN_ADDRESS)],
28+
),
29+
],
30+
utxos,
31+
},
32+
context,
33+
);
34+
35+
await addTxSignatures({
36+
unsignedTx: exportTx,
37+
privateKeys: [utils.hexToBuffer(PRIVATE_KEY)],
38+
});
39+
40+
return pvmApi.issueSignedTx(exportTx.getSignedTx());
41+
};
42+
43+
main().then(console.log);

examples/p-chain/etna/import.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { addTxSignatures, pvm, utils } from '../../../src';
2+
import { getEnvVars } from '../../utils/getEnvVars';
3+
import { getEtnaContextFromURI } from './utils/etna-context';
4+
5+
const main = async () => {
6+
const { AVAX_PUBLIC_URL, P_CHAIN_ADDRESS, PRIVATE_KEY, X_CHAIN_ADDRESS } =
7+
getEnvVars();
8+
9+
const context = await getEtnaContextFromURI(AVAX_PUBLIC_URL);
10+
11+
const pvmApi = new pvm.PVMApi(AVAX_PUBLIC_URL);
12+
13+
const { utxos } = await pvmApi.getUTXOs({
14+
sourceChain: 'X',
15+
addresses: [P_CHAIN_ADDRESS],
16+
});
17+
18+
const importTx = pvm.e.newImportTx(
19+
{
20+
fromAddressesBytes: [utils.bech32ToBytes(X_CHAIN_ADDRESS)],
21+
sourceChainId: context.xBlockchainID,
22+
toAddresses: [utils.bech32ToBytes(P_CHAIN_ADDRESS)],
23+
utxos,
24+
},
25+
context,
26+
);
27+
28+
await addTxSignatures({
29+
unsignedTx: importTx,
30+
privateKeys: [utils.hexToBuffer(PRIVATE_KEY)],
31+
});
32+
33+
return pvmApi.issueSignedTx(importTx.getSignedTx());
34+
};
35+
36+
main().then(console.log);
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Context } from '../../../../src';
2+
3+
/**
4+
* Gets the context from URI and then modifies the context
5+
* to be used for testing example Etna transactions until Etna is enabled.
6+
*/
7+
export const getEtnaContextFromURI = async (
8+
uri: string,
9+
): Promise<Context.Context> => {
10+
const context = await Context.getContextFromURI(uri);
11+
12+
return {
13+
...context,
14+
gasPrice: 10_000n,
15+
};
16+
};

examples/p-chain/etna/validate.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { addTxSignatures, networkIDs, pvm, utils } from '../../../src';
2+
import { getEnvVars } from '../../utils/getEnvVars';
3+
import { getEtnaContextFromURI } from './utils/etna-context';
4+
5+
const AMOUNT_TO_VALIDATE_AVAX: number = 1;
6+
const DAYS_TO_VALIDATE: number = 21;
7+
8+
const main = async () => {
9+
const { AVAX_PUBLIC_URL, P_CHAIN_ADDRESS, PRIVATE_KEY } = getEnvVars();
10+
11+
const pvmApi = new pvm.PVMApi(AVAX_PUBLIC_URL);
12+
13+
const context = await getEtnaContextFromURI(AVAX_PUBLIC_URL);
14+
15+
const { utxos } = await pvmApi.getUTXOs({ addresses: [P_CHAIN_ADDRESS] });
16+
17+
const startTime = await pvmApi.getTimestamp();
18+
const startDate = new Date(startTime.timestamp);
19+
const start: bigint = BigInt(startDate.getTime() / 1_000);
20+
21+
const endTime = new Date(startTime.timestamp);
22+
endTime.setDate(endTime.getDate() + DAYS_TO_VALIDATE);
23+
const end: bigint = BigInt(endTime.getTime() / 1_000);
24+
25+
const nodeId = 'NodeID-HKLp5269LH8DcrLvNDoJquQs2w1LwLCga';
26+
27+
const publicKey = utils.hexToBuffer(
28+
'0x8f95423f7142d00a48e1014a3de8d28907d420dc33b3052a6dee03a3f2941a393c2351e354704ca66a3fc29870282e15',
29+
);
30+
31+
const signature = utils.hexToBuffer(
32+
'0x86a3ab4c45cfe31cae34c1d06f212434ac71b1be6cfe046c80c162e057614a94a5bc9f1ded1a7029deb0ba4ca7c9b71411e293438691be79c2dbf19d1ca7c3eadb9c756246fc5de5b7b89511c7d7302ae051d9e03d7991138299b5ed6a570a98',
33+
);
34+
35+
const tx = pvm.e.newAddPermissionlessValidatorTx(
36+
{
37+
end,
38+
delegatorRewardsOwner: [utils.bech32ToBytes(P_CHAIN_ADDRESS)],
39+
fromAddressesBytes: [utils.bech32ToBytes(P_CHAIN_ADDRESS)],
40+
nodeId,
41+
publicKey,
42+
rewardAddresses: [utils.bech32ToBytes(P_CHAIN_ADDRESS)],
43+
shares: 20 * 1e4,
44+
signature,
45+
start,
46+
subnetId: networkIDs.PrimaryNetworkID.toString(),
47+
utxos,
48+
weight: BigInt(AMOUNT_TO_VALIDATE_AVAX * 1e9),
49+
},
50+
context,
51+
);
52+
53+
await addTxSignatures({
54+
unsignedTx: tx,
55+
privateKeys: [utils.hexToBuffer(PRIVATE_KEY)],
56+
});
57+
58+
return pvmApi.issueSignedTx(tx.getSignedTx());
59+
};
60+
61+
main().then(console.log);

examples/utils/getEnvVars.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const AVAX_PUBLIC_URL = process.env['AVAX_PUBLIC_URL'];
2+
const P_CHAIN_ADDRESS = process.env['P_CHAIN_ADDRESS'];
3+
const PRIVATE_KEY = process.env['PRIVATE_KEY'];
4+
const X_CHAIN_ADDRESS = process.env['X_CHAIN_ADDRESS'];
5+
6+
export const getEnvVars = () => {
7+
if (!(AVAX_PUBLIC_URL && P_CHAIN_ADDRESS && PRIVATE_KEY && X_CHAIN_ADDRESS)) {
8+
throw new Error('Missing environment variable(s).');
9+
}
10+
11+
return {
12+
AVAX_PUBLIC_URL,
13+
P_CHAIN_ADDRESS,
14+
PRIVATE_KEY,
15+
X_CHAIN_ADDRESS,
16+
};
17+
};

src/vms/context/context.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { getHRP } from '../../constants/networkIDs';
22
import { Info } from '../../info/info';
33
import { AVMApi } from '../avm/api';
4-
import { createEmptyDimensions } from '../common/fees/dimensions';
4+
import { createDimensions } from '../common/fees/dimensions';
55
import type { Context } from './model';
66

77
/*
@@ -52,6 +52,6 @@ export const getContextFromURI = async (
5252

5353
// TODO: Populate these values once they are exposed by the API
5454
gasPrice: 0n,
55-
complexityWeights: createEmptyDimensions(),
55+
complexityWeights: createDimensions(1, 1, 1, 1),
5656
});
5757
};

0 commit comments

Comments
 (0)