Last active
September 29, 2021 18:51
-
-
Save cgcardona/d586cf07d8ac25048feccf6eac68b9e2 to your computer and use it in GitHub Desktop.
Script to create new subnet, add validators to subnet and create new blockchain on AVA.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 1. Create Subnet | |
// 1. Create Users | |
// 2. Generate Conrol Keys | |
// 3. Export/Import User | |
// 2. Adding a Validator to a Subnet | |
// 1. Add a Validator to the Default Subnet | |
// 2. Add a Validator to a Non-default Subnet | |
// 3. Create a New Blockchain | |
// 1. Create the Genesis Data | |
// 2. Interact With the New Blockchain | |
// based on steps found here: | |
// * https://docs.ava.network/v1.0/en/tutorials/create-a-subnet | |
// * https://docs.ava.network/v1.0/en/tutorials/adding-validators | |
// * https://docs.ava.network/v1.0/en/tutorials/create-a-blockchain | |
// imports | |
import * as slopes from "slopes" | |
import axios, { AxiosResponse } from "axios" | |
// interfaces | |
interface Subnet { | |
id: string, | |
controlKeys: string[], | |
threshold: string | |
} | |
interface Account { | |
address: string, | |
nonce: string, | |
balance: string | |
} | |
interface Validator { | |
id: string, | |
startTime: string, | |
endtime: string, | |
stakeAmount: string | |
} | |
interface FixedCap { | |
amount: number, | |
address: string | |
} | |
interface InitialState { | |
fixedCap: FixedCap[] | |
} | |
interface AssetAlias { | |
name: string, | |
symbol: string, | |
initialState: InitialState | |
} | |
interface VariableCap { | |
minters: string[], | |
threshold: number | |
} | |
interface InitialStateUnique { | |
variableCap: VariableCap[] | |
} | |
interface AssetAliasCanBeAnythingUnique { | |
name: string, | |
symbol: string, | |
initialState: InitialStateUnique | |
} | |
interface GenesisData { | |
genesisData: { | |
asset1: AssetAlias, | |
asset2: AssetAliasCanBeAnythingUnique | |
} | |
} | |
interface Blockchain { | |
id: string, | |
name: string, | |
subnetID: string, | |
vmID: string | |
} | |
const ip: string = "" | |
const port: number = 9650 | |
const protocol: string = "http" | |
const networkID: number = 12345 | |
const url: string = `${protocol}://${ip}:${port}` | |
const ava: slopes.Slopes = new slopes.Slopes(ip, port, protocol, networkID) | |
const nodeKeys: slopes.Keystore = ava.NodeKeys() | |
const username1: string = "" | |
const password1: string = "" | |
console.log(`Username1: ${username1}`) | |
const username2: string = "" | |
const password2: string = "" | |
console.log(`Username2: ${username2}`) | |
// boilerplate | |
const httpReq = async (path: string, method: string, params: object = {}): Promise<AxiosResponse> => { | |
const response: AxiosResponse = await axios.post(`${url}/ext/${path}`, { | |
jsonrpc: '2.0', | |
id: 1, | |
method: method, | |
params: params | |
}, { | |
headers: { | |
'content-type': 'application/json' | |
} | |
}) | |
return response | |
} | |
// the goods | |
const main = async (): Promise<any> => { | |
console.log(`Create a Subnet`) | |
console.log(`Create the first user`) | |
let user1: boolean = await nodeKeys.createUser(username1, password1) | |
console.log(`user1 was created: ${user1}`) | |
console.log(`Create the second user`) | |
let user2: boolean = await nodeKeys.createUser(username2, password2) | |
console.log(`user2 was created: ${user2}`) | |
console.log(`Generate the Control Keys`) | |
let response: AxiosResponse = await httpReq("P", "platform.createAccount", { | |
username: username1, | |
password: password1 | |
}) | |
console.log(`Generate the first control key`) | |
let controlKey1: string = response.data.result.address | |
console.log(`controlKey1: ${controlKey1}`) | |
response = await httpReq("P", "platform.createAccount", { | |
username: username2, | |
password: password2 | |
}) | |
console.log(`Generate the second control key`) | |
let controlKey2: string = response.data.result.address | |
console.log(`controlKey2: ${controlKey2}`) | |
console.log(`Create the Unsigned Transaction`) | |
response = await httpReq("P", "platform.createSubnet", { | |
controlKeys: [ | |
controlKey1, | |
controlKey2 | |
], | |
threshold: 2, | |
payerNonce: 1 | |
}) | |
let unsignedTx: string = response.data.result.unsignedTx | |
console.log(`unsignedTx: ${unsignedTx}`) | |
// TODO - is `signer` a P-Address? | |
let pAddress: string = "" | |
console.log(`Sign the Transaction`) | |
response = await httpReq("P", "platform.sign", { | |
tx: unsignedTx, | |
signer: pAddress, | |
username: username1, | |
password: password1 | |
}) | |
let tx: string = response.data.result.Tx | |
console.log(`tx: ${tx}`) | |
console.log(`Issue the Transaction`) | |
response = await httpReq("P", "platform.issueTx", { | |
tx: tx | |
}) | |
let txID: string = response.data.result.txID | |
console.log(`txID: ${txID}`) | |
console.log(`Verifying Success`) | |
response = await httpReq("P", "platform.getSubnets", { | |
tx: tx | |
}) | |
let subnets: Subnet[] = response.data.result.subnets | |
console.log(`subnets: `) | |
console.log(subnets) | |
console.log(`Export a User`) | |
response = await httpReq("keystore", "keystore.exportUser", { | |
username: username1, | |
password: password1 | |
}) | |
let user: string = response.data.result.user | |
console.log(`user: ${user}`) | |
console.log(`Import a User`) | |
response = await httpReq("keystore", "keystore.importUser", { | |
username: username1, | |
password: password1, | |
user: user | |
}) | |
let accounts: Account[] = response.data.result.accounts | |
console.log(`accounts:`) | |
console.log(`${accounts}`) | |
console.log(`-------------------------------`) | |
console.log(`Add a Validator to the Default Subnet`) | |
console.log(`Get Node ID`) | |
response = await httpReq("admin", "admin.getNodeID") | |
let nodeID: string = response.data.result.nodeID | |
console.log(`nodeID: ${nodeID}`) | |
console.log(`Get Nonce`) | |
response = await httpReq("P", "platform.getAccount", { | |
address: pAddress | |
}) | |
let nonce: string = response.data.result.nonce | |
console.log(`nonce: ${nonce}`) | |
console.log(`Stake amount`) | |
console.log(`Create the Unsigned Transaction`) | |
// TODO: add DateTime | |
// TODO: add moment https://momentjs.com | |
let startTime: string = "" | |
let endTime: string = "" | |
response = await httpReq("P", "platform.addDefaultSubnetValidator", { | |
id: nodeID, | |
payerNonce: nonce, | |
destination: controlKey1, | |
startTime: startTime, | |
endTime: endTime, | |
stakeAmount: 1000000, | |
delegationFeeRate: 100000 | |
}) | |
unsignedTx = response.data.result.unsignedTx | |
console.log(`unsignedTx: ${unsignedTx}`) | |
console.log(`Sign the Transaction`) | |
response = await httpReq("P", "platform.sign", { | |
tx: unsignedTx, | |
signer: pAddress, | |
username: username1, | |
password: password1 | |
}) | |
tx = response.data.result.Tx | |
console.log(`tx: ${tx}`) | |
console.log(`Issue the Transaction`) | |
response = await httpReq("P", "platform.issueTx", { | |
tx: tx | |
}) | |
txID = response.data.result.txID | |
console.log(`txID: ${txID}`) | |
console.log(`Verify Success`) | |
response = await httpReq("P", "platform.getPendingValidators") | |
let validators: Validator[] = response.data.result.validators | |
console.log(`validators: `) | |
console.log(`${validators}`) | |
// TODO - Get subnetID | |
let subnetID: string = "" | |
console.log(`Get Nonce`) | |
response = await httpReq("P", "platform.getAccount", { | |
address: pAddress | |
}) | |
nonce = response.data.result.nonce | |
console.log(`nonce: ${nonce}`) | |
console.log(`Add a Validator to a Non-default Subnet`) | |
response = await httpReq("P", "platform.addNonDefaultSubnetValidator", { | |
id: nodeID, | |
subnetID: subnetID, | |
startTime: startTime, | |
endTime: endTime, | |
weight: 1, | |
payerNonce: nonce | |
}) | |
unsignedTx = response.data.result.unsignedTx | |
console.log(`unsignedTx: ${unsignedTx}`) | |
console.log(`Sign the Transaction`) | |
// TODO - confirm signer | |
response = await httpReq("P", "platform.sign", { | |
tx: unsignedTx, | |
signer: controlKey1, | |
username: username1, | |
password: password1 | |
}) | |
tx = response.data.result.Tx | |
console.log(`tx: ${tx}`) | |
response = await httpReq("P", "platform.sign", { | |
tx: tx, | |
signer: controlKey2, | |
username: username2, | |
password: password2 | |
}) | |
tx = response.data.result.Tx | |
console.log(`tx: ${tx}`) | |
response = await httpReq("P", "platform.sign", { | |
tx: tx, | |
signer: controlKey2, | |
username: username2, | |
password: password2 | |
}) | |
tx = response.data.result.Tx | |
console.log(`tx: ${tx}`) | |
console.log(`Issue the Transaction`) | |
response = await httpReq("P", "platform.issueTx", { | |
tx: tx | |
}) | |
txID = response.data.result.txID | |
console.log(`txID: ${txID}`) | |
console.log(`Verify Success`) | |
response = await httpReq("P", "platform.getPendingValidators") | |
validators = response.data.result.validators | |
console.log(`validators: `) | |
console.log(`${validators}`) | |
console.log(`-------------------------------`) | |
console.log(`Create the Genesis Data`) | |
let genesisData: GenesisData = { | |
genesisData: { | |
asset1: { | |
name: "myFixedCapAsset", | |
symbol: "MFCA", | |
initialState: { | |
fixedCap : [ | |
{ | |
amount: 1000, | |
address: controlKey1 | |
}, | |
{ | |
amount: 5000, | |
address: controlKey2 | |
} | |
] | |
} | |
}, | |
asset2: { | |
name: "myVarCapAsset", | |
symbol: "MVCA", | |
initialState: { | |
variableCap : [ | |
{ | |
minters: [ | |
controlKey1, | |
controlKey2 | |
], | |
threshold: 1 | |
}, | |
] | |
} | |
} | |
} | |
} | |
let bytes: string = response.data.result.bytes | |
console.log(`bytes: ${bytes}`) | |
console.log(`Create the Unsigned Transaction`) | |
console.log(`Get Nonce`) | |
response = await httpReq("P", "platform.getAccount", { | |
address: pAddress | |
}) | |
nonce = response.data.result.nonce | |
response = await httpReq("P", "platform.createBlockchain", { | |
subnetID: subnetID, | |
vmID: "avm", | |
name: "My new AVM", | |
payerNonce: nonce, | |
genesisData: bytes | |
}) | |
unsignedTx = response.data.result.unsignedTx | |
console.log(`unsignedTx: ${unsignedTx}`) | |
console.log(`Sign the Transaction`) | |
response = await httpReq("P", "platform.sign", { | |
tx: unsignedTx, | |
signer: controlKey1, | |
username: username1, | |
password: password1 | |
}) | |
tx = response.data.result.tx | |
console.log(`tx: ${tx}`) | |
response = await httpReq("P", "platform.sign", { | |
tx: tx, | |
signer: controlKey2, | |
username: username2, | |
password: password2 | |
}) | |
tx = response.data.result.tx | |
console.log(`tx: ${tx}`) | |
response = await httpReq("P", "platform.sign", { | |
tx: tx, | |
signer: pAddress, | |
username: username1, | |
password: password1 | |
}) | |
tx = response.data.result.tx | |
console.log(`tx: ${tx}`) | |
console.log(`Issue the Transaction`) | |
response = await httpReq("P", "platform.issueTx", { | |
tx: tx | |
}) | |
txID = response.data.result.txID | |
console.log(`txID: ${txID}`) | |
console.log(`Confirm Success`) | |
response = await httpReq("P", "platform.issueTx") | |
let blockchains: Blockchain[] = response.data.result.blockchains | |
console.log(`blockchains: `) | |
console.log(`${blockchains}`) | |
console.log(`Interact With the New Blockchain`) | |
response = await httpReq(`bc/${blockchains[0].id}`, "avm.getBalance", { | |
address: controlKey1, | |
assetID: "asset1" | |
}) | |
let balance: string = response.data.result.balance | |
console.log(`blockchains: ${balance}`) | |
} | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment