diff --git a/dev/node/basicSendTx.ts b/dev/node/basicSendTx.ts new file mode 100644 index 0000000..4e5a833 --- /dev/null +++ b/dev/node/basicSendTx.ts @@ -0,0 +1,60 @@ +import { Client, Wallet, Obi, Message, Coin, Transaction, Fee } from '../../lib' + +const grpcEndpoint = 'https://laozi-testnet6.bandchain.org/grpc-web' +const client = new Client(grpcEndpoint) + +export async function exampleSendBlockTransaction() { + // Step 1: Import a private key for signing transaction + const { PrivateKey } = Wallet + const mnemonic = 'test' + const privateKey = PrivateKey.fromMnemonic(mnemonic) + const pubkey = privateKey.toPubkey() + const sender = pubkey.toAddress().toAccBech32() + + // Step 2.1: Prepare oracle request's properties + const obi = new Obi('{symbols:[string],multiplier:u64}/{rates:[u64]}') + const calldata = obi.encodeInput({ symbols: ['ETH'], multiplier: 100 }) + let coin = new Coin() + coin.setDenom('uband') + coin.setAmount('1000000') + + let feeCoin = new Coin() + feeCoin.setDenom('uband') + feeCoin.setAmount('5000') + + // Step 2.2: Create an oracle request message + const requestMessage = new Message.MsgRequestData( + 37, + calldata, + 4, + 3, + 'BandProtocol', + sender, + [coin], + 50000, + 200000, + ) + + // Step 3.1: Construct a transaction + const fee = new Fee() + fee.setAmountList([feeCoin]) + fee.setGasLimit(1000000) + const chainId = await client.getChainId() + const txn = new Transaction() + txn.withMessages(requestMessage) + await txn.withSender(client, sender) + txn.withChainId(chainId) + txn.withFee(fee) + txn.withMemo('') + + // Step 3.2: Sign the transaction using the private key + const signDoc = txn.getSignDoc(pubkey) + const signature = privateKey.sign(signDoc) + + const txRawBytes = txn.getTxData(signature, pubkey) + + // Step 4: Broadcast the transaction + const sendTx = await client.sendTxBlockMode(txRawBytes) + + return sendTx +} diff --git a/dev/node/dataSource.ts b/dev/node/dataSource.ts new file mode 100644 index 0000000..59ab740 --- /dev/null +++ b/dev/node/dataSource.ts @@ -0,0 +1,127 @@ +import { Client, Wallet, Message, Coin, Transaction, Fee } from '../../lib' +import fs from 'fs' +import path from 'path' + +const grpcEndpoint = 'https://laozi-testnet6.bandchain.org/grpc-web' +const client = new Client(grpcEndpoint) +const { PrivateKey } = Wallet +const mnemonic = 'test' +const privateKey = PrivateKey.fromMnemonic(mnemonic) +const pubkey = privateKey.toPubkey() +const sender = pubkey.toAddress().toAccBech32() + +export async function exampleCreateDataSource() { + // don't forget to copy this file when you copy the code + const execPath = path.resolve(__dirname, './mock/example_data_source.py') + const file = fs.readFileSync(execPath, 'utf8') + const executable = Buffer.from(file).toString('base64') + + let coin = new Coin() + coin.setDenom('uband') + coin.setAmount('1000000') + + let feeCoin = new Coin() + feeCoin.setDenom('uband') + feeCoin.setAmount('5000') + + // Step 2.2: Create an oracle request message + + // name: string + // executable: Buffer | string + // treasury: string + // owner: string + // sender: string + // feeList: Coin[] + // description?: string + const requestMessage = new Message.MsgCreateDataSource( + 'Test DS NodeJs', + executable, + sender, + sender, + sender, + [feeCoin], + 'Test DS NodeJs Description', + ) + + // Step 3.1: Construct a transaction + const fee = new Fee() + fee.setAmountList([feeCoin]) + fee.setGasLimit(1000000) + const chainId = await client.getChainId() + const txn = new Transaction() + txn.withMessages(requestMessage) + await txn.withSender(client, sender) + txn.withChainId(chainId) + txn.withFee(fee) + txn.withMemo('') + + // Step 3.2: Sign the transaction using the private key + const signDoc = txn.getSignDoc(pubkey) + const signature = privateKey.sign(signDoc) + + const txRawBytes = txn.getTxData(signature, pubkey) + + // Step 4: Broadcast the transaction + const sendTx = await client.sendTxBlockMode(txRawBytes) + + return sendTx +} + +export async function exampleEditDataSource(id: number) { + // don't forget to copy this file when you copy the code + const execPath = path.resolve(__dirname, './mock/example_data_source.py') + const file = fs.readFileSync(execPath, 'utf8') + const executable = Buffer.from(file).toString('base64') + + let coin = new Coin() + coin.setDenom('uband') + coin.setAmount('1000000') + + let feeCoin = new Coin() + feeCoin.setDenom('uband') + feeCoin.setAmount('5000') + + // Step 2.2: Create an oracle request message + + // dataSourceId: number + // treasury: string + // owner: string + // sender: string + // feeList: Coin[] + // name: string + // description: string + // executable: Buffer | string + const requestMessage = new Message.MsgEditDataSource( + id, + sender, + sender, + sender, + [feeCoin], + 'Test Edit DS NodeJs', + 'Test Edit DS NodeJs Description', + executable, + ) + + // Step 3.1: Construct a transaction + const fee = new Fee() + fee.setAmountList([feeCoin]) + fee.setGasLimit(1000000) + const chainId = await client.getChainId() + const txn = new Transaction() + txn.withMessages(requestMessage) + await txn.withSender(client, sender) + txn.withChainId(chainId) + txn.withFee(fee) + txn.withMemo('') + + // Step 3.2: Sign the transaction using the private key + const signDoc = txn.getSignDoc(pubkey) + const signature = privateKey.sign(signDoc) + + const txRawBytes = txn.getTxData(signature, pubkey) + + // Step 4: Broadcast the transaction + const sendTx = await client.sendTxBlockMode(txRawBytes) + + return sendTx +} diff --git a/dev/node/getReferenceData.ts b/dev/node/getReferenceData.ts new file mode 100644 index 0000000..1fe0276 --- /dev/null +++ b/dev/node/getReferenceData.ts @@ -0,0 +1,11 @@ +import { Client } from '../../lib' + +const grpcEndpoint = 'https://laozi-testnet6.bandchain.org/grpc-web' +const client = new Client(grpcEndpoint) + +// This example demonstrates how to query price data from +// Band's standard dataset +export async function exampleGetReferenceData() { + const rate = await client.getReferenceData(['BTC/USD', 'ETH/BTC'], 3, 4) + return rate +} diff --git a/dev/node/index.ts b/dev/node/index.ts new file mode 100644 index 0000000..92e94d3 --- /dev/null +++ b/dev/node/index.ts @@ -0,0 +1,28 @@ +import { exampleCreateDataSource, exampleEditDataSource } from './dataSource' +import { exampleSendBlockTransaction } from './basicSendTx' +import { exampleGetReferenceData } from './getReferenceData' +import { + exampleCreateOracleScript, + exampleEditOracleScript, +} from './oracleScript' +;(async () => { + console.log('Creating a new data source...') + const responseDS = await exampleCreateDataSource() + const rawLogDS = JSON.parse(responseDS.rawLog) + const datasourceID = rawLogDS[0].events[0].attributes[0].value + console.log(responseDS) + console.log('Editing a new data source...') + console.log(await exampleEditDataSource(datasourceID)) + console.log('Test sending an oracle request...') + console.log(await exampleSendBlockTransaction()) + console.log('Test getting reference data...') + console.log(await exampleGetReferenceData()) + console.log('Creating an oracle script...') + console.log(await exampleCreateOracleScript()) + const responseOS = await exampleCreateOracleScript() + const rawLogOS = JSON.parse(responseOS.rawLog) + const oraclescriptID = rawLogOS[0].events[0].attributes[0].value + console.log(responseOS) + console.log('Editing an oracle script...') + console.log(await exampleEditOracleScript(oraclescriptID)) +})() diff --git a/dev/node/mock/example_data_source.py b/dev/node/mock/example_data_source.py new file mode 100644 index 0000000..350e747 --- /dev/null +++ b/dev/node/mock/example_data_source.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 + +import sys +import json +import requests + +HEADERS = {"Content-Type": "application/json"} + +SYMBOLS_WITH_WEIGHTS = [ + ["BTC", 0.004909683753206196], + ["ETH", 0.13310406316230874], + ["BNB", 0.14811355573986523], + ["EOS", 8.953653071560828], + ["XTZ", 9.094515911727951], + ["ATOM", 1.7587624274324516], + ["YFI", 0.0010102624194177228], + ["BCH", 0.02036657498252182], + ["TRX", 205.4816659023913], + ["HT", 0.6857067994908471], + ["OKB", 0.5980410214630887], + ["ZIL", 87.2055371354679], + ["CRO", 69.95450022346525], + ["XLM", 23.053273306237845], + ["ADA", 7.179120672821946], + ["DOT", 0.27893252164401366], + ["SNX", 0.5011997921585194], + ["ALGO", 9.192726225525655], + ["OMG", 2.1996607471011007], + ["COMP", 0.023306593928026486], + ["NEO", 0.19421422582454298], + ["VET", 171.95165365836635], + ["BAT", 13.126425414588228], + ["AAVE", 0.019770547127068678], + ["LINK", 0.2764242681323155], + ["THETA", 2.176840201683421], + ["LEO", 3.5708266638194557], + ["KNC", 4.3561169623294544], + ["LTC", 0.0413220565629011], + ["ZRX", 5.640930140168719], + ["XRP", 16.427604258162788], + ["MKR", 0.003358561719070429], + ["CELO", 1.7828863706544964], + ["FTT", 0.5340837373118201], + ["BTT", 12062.322952053712], + ["REN", 13.314915914819395], + ["QTUM", 2.8585514788368362], + ["DGB", 62.22667438038412], + ["ONT", 3.754157138230833], + ["ICX", 2.2741324674258427], + ["KSM", 0.01489803116735643], + ["UMA", 0.16281776279745758], + ["XEM", 5.280971599079332], + ["MIOTA", 2.828955811666102], +] + + +def main(url): + symbols, weights = zip(*SYMBOLS_WITH_WEIGHTS) + payload = {"symbols": symbols, "min_count": 10, "ask_count": 16} + result = requests.request("POST", url, headers=HEADERS, json=payload).json() + prices = [float(px["px"]) / float(px["multiplier"]) for px in result["result"]] + acc = 0 + for (p, w) in zip(prices, weights): + acc += float(p) * w + return acc + + +if __name__ == "__main__": + try: + print(main(*sys.argv[1:])) + except Exception as e: + print(str(e), file=sys.stderr) + sys.exit(1) diff --git a/dev/node/mock/example_oracle_script.wasm b/dev/node/mock/example_oracle_script.wasm new file mode 100644 index 0000000..4b08fb9 Binary files /dev/null and b/dev/node/mock/example_oracle_script.wasm differ diff --git a/dev/node/mock/standard_dataset_crypto_mainnet.wasm b/dev/node/mock/standard_dataset_crypto_mainnet.wasm new file mode 100644 index 0000000..9db2508 Binary files /dev/null and b/dev/node/mock/standard_dataset_crypto_mainnet.wasm differ diff --git a/dev/node/oracleScript.ts b/dev/node/oracleScript.ts new file mode 100644 index 0000000..9e272bf --- /dev/null +++ b/dev/node/oracleScript.ts @@ -0,0 +1,112 @@ +import { Client, Wallet, Message, Coin, Transaction, Fee } from '../../lib' +import fs from 'fs' +import path from 'path' + +const grpcEndpoint = 'https://laozi-testnet6.bandchain.org/grpc-web' +const client = new Client(grpcEndpoint) +const { PrivateKey } = Wallet +const mnemonic = 'test' +const privateKey = PrivateKey.fromMnemonic(mnemonic) +const pubkey = privateKey.toPubkey() +const sender = pubkey.toAddress().toAccBech32() +const owner = 'band18e55d9xyrgyg3tk72zmg7s92uu8sd95jzgj73a' + +export async function exampleCreateOracleScript() { + // don't forget to copy this file when you copy the code + const execPath = path.resolve( + __dirname, + './mock/standard_dataset_crypto_mainnet.wasm', + ) + const code = fs.readFileSync(execPath) + + let feeCoin = new Coin() + feeCoin.setDenom('uband') + feeCoin.setAmount('5000') + + // Step 2.2: Create an oracle request message + + // name: string + // code: Buffer + // owner: string + // sender: string + // description?: string + // schema?: string + // sourceCodeUrl?: string + const requestMessage = new Message.MsgCreateOracleScript( + 'Oracle Script Name', + code, + sender, + sender, + 'Oracle Script Description', + '{symbols:[string],multiplier:u64}/{rates:[u64]}', + 'https://mockurl.com', + ) + + const fee = new Fee() + fee.setAmountList([feeCoin]) + fee.setGasLimit(1500000) + const chainId = await client.getChainId() + const txn = new Transaction() + txn.withMessages(requestMessage) + await txn.withSender(client, sender) + txn.withChainId(chainId) + txn.withFee(fee) + txn.withMemo('') + + const signDoc = txn.getSignDoc(pubkey) + const signature = privateKey.sign(signDoc) + + const txRawBytes = txn.getTxData(signature, pubkey) + const sendTx = await client.sendTxBlockMode(txRawBytes) + return sendTx +} + +export async function exampleEditOracleScript(id: number) { + // don't forget to copy this file when you copy the code + const execPath = path.resolve(__dirname, './mock/example_oracle_script.wasm') + const code = fs.readFileSync(execPath) + + let feeCoin = new Coin() + feeCoin.setDenom('uband') + feeCoin.setAmount('5000') + + // Step 2.2: Create an oracle request message + + // oracleScriptId: number + // owner: string + // sender: string + // name: string + // description: string + // schema: string + // sourceCodeUrl: string + // code: Buffer | string + const requestMessage = new Message.MsgEditOracleScript( + id, + owner, + sender, + 'Edit Oracle Script Name', + 'Edit Oracle Script Description', + '{symbols:[string],multiplier:u64}/{rates:[u64]}', + 'https://mockurl.com', + code, + ) + + const fee = new Fee() + fee.setAmountList([feeCoin]) + fee.setGasLimit(1500000) + const chainId = await client.getChainId() + const txn = new Transaction() + txn.withMessages(requestMessage) + await txn.withSender(client, sender) + txn.withChainId(chainId) + txn.withFee(fee) + txn.withMemo('') + + const signDoc = txn.getSignDoc(pubkey) + const signature = privateKey.sign(signDoc) + + const txRawBytes = txn.getTxData(signature, pubkey) + const sendTx = await client.sendTxBlockMode(txRawBytes) + + return sendTx +}