@bandprotocol/bandchain.js
Version:
Library for interacting with BandChain in browser and Node.js environments
513 lines (492 loc) • 22.3 kB
text/typescript
import { Client } from '../../src'
import { grpc } from '@improbable-eng/grpc-web'
import { ServiceClient as TxServiceClient } from '../../codegen/cosmos/tx/v1beta1/service_pb_service'
import {
ServiceError,
UnaryResponse,
} from '../../codegen/oracle/v1/query_pb_service'
import {
BroadcastTxRequest,
BroadcastTxResponse,
} from '../../codegen/cosmos/tx/v1beta1/service_pb'
import { TxResponse } from '../../codegen/cosmos/base/abci/v1beta1/abci_pb'
import {
ABCIMessageLog,
StringEvent,
Attribute,
} from '../../codegen/cosmos/base/abci/v1beta1/abci_pb'
jest.mock('../../codegen/cosmos/tx/v1beta1/service_pb_service')
const MockedTxService = jest.mocked(TxServiceClient)
const TEST_GRPC = 'http://localhost:8080'
const expectedSignatureFailed = {
height: 0,
txhash: 'C6FCF7AB773EFE9D616DBD0C2B09CAF552C8998CABBF17A394B5243CAA9381E0',
codespace: 'sdk',
code: 4,
data: '',
eventsList: [],
rawLog:
'signature verification failed; please verify account number (104) and chain-id (band-laozi-testnet6): unauthorized',
logsList: [],
info: '',
gasWanted: 2000000,
gasUsed: 39362,
tx: undefined,
timestamp: '',
}
beforeEach(() => {
MockedTxService.mockClear()
})
describe('send transaction sync mode', () => {
it('sync mode success', async () => {
expect(MockedTxService).not.toHaveBeenCalled()
const client = new Client(TEST_GRPC)
expect(MockedTxService).toHaveBeenCalledTimes(1)
const mockedTxServices = jest.mocked(MockedTxService.mock.instances[0])
type ExpectedDataSourceSignature = (
requestMessage: BroadcastTxRequest,
metadata: grpc.Metadata,
callback: (
error: ServiceError | null,
responseMessage: BroadcastTxResponse | null,
) => void,
) => UnaryResponse
const mockedBroadcasting = jest.mocked(
mockedTxServices.broadcastTx as ExpectedDataSourceSignature,
{
shallow: true,
},
)
mockedBroadcasting.mockImplementationOnce(
(_req, _metadata, callback): UnaryResponse => {
const response = new BroadcastTxResponse()
const txResponse = new TxResponse()
txResponse.setCode(0)
txResponse.setTxhash(
'B7ACAEE66D48CF24B0F752A1D0B25E055CE2B49F1BC7F7D77EEE80269C5176DF',
)
response.setTxResponse(txResponse)
callback(null, response)
return { cancel: function () {} }
},
)
const expected = {
height: 0,
txhash:
'B7ACAEE66D48CF24B0F752A1D0B25E055CE2B49F1BC7F7D77EEE80269C5176DF',
codespace: '',
code: 0,
data: '',
eventsList: [],
rawLog: '',
logsList: [],
info: '',
gasWanted: 0,
gasUsed: 0,
tx: undefined,
timestamp: '',
}
const response = await client.sendTxSyncMode('txBytes')
expect(mockedBroadcasting).toHaveBeenCalledTimes(1)
expect(response).toEqual(expected)
})
it('sync mode signature fail', async () => {
expect(MockedTxService).not.toHaveBeenCalled()
const client = new Client(TEST_GRPC)
expect(MockedTxService).toHaveBeenCalledTimes(1)
const mockedTxServices = jest.mocked(MockedTxService.mock.instances[0])
type ExpectedDataSourceSignature = (
requestMessage: BroadcastTxRequest,
metadata: grpc.Metadata,
callback: (
error: ServiceError | null,
responseMessage: BroadcastTxResponse | null,
) => void,
) => UnaryResponse
const mockedBroadcasting = jest.mocked(
mockedTxServices.broadcastTx as ExpectedDataSourceSignature,
{
shallow: true,
},
)
mockedBroadcasting.mockImplementationOnce(
(_req, _metadata, callback): UnaryResponse => {
const response = new BroadcastTxResponse()
const txResponse = new TxResponse()
txResponse.setHeight(0)
txResponse.setCodespace('sdk')
txResponse.setCode(4)
txResponse.setTxhash(
'C6FCF7AB773EFE9D616DBD0C2B09CAF552C8998CABBF17A394B5243CAA9381E0',
)
txResponse.setRawLog(
'signature verification failed; please verify account number (104) and chain-id (band-laozi-testnet6): unauthorized',
),
txResponse.setGasWanted(2000000)
txResponse.setGasUsed(39362)
response.setTxResponse(txResponse)
callback(null, response)
return { cancel: function () {} }
},
)
expectedSignatureFailed
const response = await client.sendTxAsyncMode('txBytesFail')
expect(mockedBroadcasting).toHaveBeenCalledTimes(1)
expect(response).toEqual(expectedSignatureFailed)
})
})
describe('send transaction async mode', () => {
it('asyn mode success', async () => {
expect(MockedTxService).not.toHaveBeenCalled()
const client = new Client(TEST_GRPC)
expect(MockedTxService).toHaveBeenCalledTimes(1)
const mockedTxServices = jest.mocked(MockedTxService.mock.instances[0])
type ExpectedDataSourceSignature = (
requestMessage: BroadcastTxRequest,
metadata: grpc.Metadata,
callback: (
error: ServiceError | null,
responseMessage: BroadcastTxResponse | null,
) => void,
) => UnaryResponse
const mockedBroadcasting = jest.mocked(
mockedTxServices.broadcastTx as ExpectedDataSourceSignature,
{
shallow: true,
},
)
mockedBroadcasting.mockImplementationOnce(
(_req, _metadata, callback): UnaryResponse => {
const response = new BroadcastTxResponse()
const txResponse = new TxResponse()
txResponse.setCode(0)
txResponse.setTxhash(
'B7ACAEE66D48CF24B0F752A1D0B25E055CE2B49F1BC7F7D77EEE80269C5176DF',
)
response.setTxResponse(txResponse)
callback(null, response)
return { cancel: function () {} }
},
)
const expected = {
height: 0,
txhash:
'B7ACAEE66D48CF24B0F752A1D0B25E055CE2B49F1BC7F7D77EEE80269C5176DF',
codespace: '',
code: 0,
data: '',
eventsList: [],
rawLog: '',
logsList: [],
info: '',
gasWanted: 0,
gasUsed: 0,
tx: undefined,
timestamp: '',
}
const response = await client.sendTxAsyncMode('txBytes')
expect(mockedBroadcasting).toHaveBeenCalledTimes(1)
expect(response).toEqual(expected)
})
})
describe('send transaction block mode', () => {
it('block mode success', async () => {
expect(MockedTxService).not.toHaveBeenCalled()
const client = new Client(TEST_GRPC)
expect(MockedTxService).toHaveBeenCalledTimes(1)
const mockedTxServices = jest.mocked(MockedTxService.mock.instances[0])
type ExpectedDataSourceSignature = (
requestMessage: BroadcastTxRequest,
metadata: grpc.Metadata,
callback: (
error: ServiceError | null,
responseMessage: BroadcastTxResponse | null,
) => void,
) => UnaryResponse
const mockedBroadcasting = jest.mocked(
mockedTxServices.broadcastTx as ExpectedDataSourceSignature,
{
shallow: true,
},
)
mockedBroadcasting.mockImplementationOnce(
(_req, _metadata, callback): UnaryResponse => {
const response = new BroadcastTxResponse()
const txResponse = new TxResponse()
txResponse.setHeight(272796)
txResponse.setTxhash(
'E894BB773470ADB28D8FA61BF5300A23D6BA04D2F28A6AF2E7DA5AB4122FA3E0',
)
txResponse.setCodespace('')
txResponse.setCode(0)
txResponse.setData('0A090A0772657175657374')
txResponse.setRawLog(
'[{"events":[{"type":"message","attributes":[{"key":"action","value":"request"}]},{"type":"raw_request","attributes":[{"key":"data_source_id","value":"61"},{"key":"data_source_hash","value":"07be7bd61667327aae10b7a13a542c7dfba31b8f4c52b0b60bf9c7b11b1a72ef"},{"key":"external_id","value":"6"},{"key":"calldata","value":"ETH"},{"key":"fee"},{"key":"data_source_id","value":"57"},{"key":"data_source_hash","value":"61b369daa5c0918020a52165f6c7662d5b9c1eee915025cb3d2b9947a26e48c7"},{"key":"external_id","value":"0"},{"key":"calldata","value":"ETH"},{"key":"fee"},{"key":"data_source_id","value":"62"},{"key":"data_source_hash","value":"107048da9dbf7960c79fb20e0585e080bb9be07d42a1ce09c5479bbada8d0289"},{"key":"external_id","value":"3"},{"key":"calldata","value":"ETH"},{"key":"fee"},{"key":"data_source_id","value":"60"},{"key":"data_source_hash","value":"2e588de76a58338125022bc42b460072300aebbcc4acaf55f91755c1c1799bac"},{"key":"external_id","value":"5"},{"key":"calldata","value":"huobipro ETH"},{"key":"fee"},{"key":"data_source_id","value":"59"},{"key":"data_source_hash","value":"5c011454981c473af3bf6ef93c76b36bfb6cc0ce5310a70a1ba569de3fc0c15d"},{"key":"external_id","value":"2"},{"key":"calldata","value":"ETH"},{"key":"fee"},{"key":"data_source_id","value":"60"},{"key":"data_source_hash","value":"2e588de76a58338125022bc42b460072300aebbcc4acaf55f91755c1c1799bac"},{"key":"external_id","value":"4"},{"key":"calldata","value":"binance ETH"},{"key":"fee"},{"key":"data_source_id","value":"60"},{"key":"data_source_hash","value":"2e588de76a58338125022bc42b460072300aebbcc4acaf55f91755c1c1799bac"},{"key":"external_id","value":"9"},{"key":"calldata","value":"bittrex ETH"},{"key":"fee"},{"key":"data_source_id","value":"60"},{"key":"data_source_hash","value":"2e588de76a58338125022bc42b460072300aebbcc4acaf55f91755c1c1799bac"},{"key":"external_id","value":"7"},{"key":"calldata","value":"kraken ETH"},{"key":"fee"},{"key":"data_source_id","value":"60"},{"key":"data_source_hash","value":"2e588de76a58338125022bc42b460072300aebbcc4acaf55f91755c1c1799bac"},{"key":"external_id","value":"8"},{"key":"calldata","value":"bitfinex ETH"},{"key":"fee"},{"key":"data_source_id","value":"58"},{"key":"data_source_hash","value":"7e6759fade717a06fb643392bfde837bfc3437da2ded54feed706e6cd35de461"},{"key":"external_id","value":"1"},{"key":"calldata","value":"ETH"},{"key":"fee"}]},{"type":"request","attributes":[{"key":"id","value":"37643"},{"key":"client_id","value":"Blue"},{"key":"oracle_script_id","value":"37"},{"key":"calldata","value":"00000001000000034554480000000000000064"},{"key":"ask_count","value":"4"},{"key":"min_count","value":"3"},{"key":"gas_used","value":"71512"},{"key":"total_fees"},{"key":"validator","value":"bandvaloper19eu9g3gka6rxlevkjlvjq7s6c498tejnwxjwxx"},{"key":"validator","value":"bandvaloper1p46uhvdk8vr829v747v85hst3mur2dzlhfemmz"},{"key":"validator","value":"bandvaloper1a570h9e3rtvfhm030ta5hvel7e7e4lh4pgv8wj"},{"key":"validator","value":"bandvaloper1274qgg28xkz6f3upx05ftr9zepgmtfgts392dy"}]}]}]',
)
const ABCIMsgLog = new ABCIMessageLog()
ABCIMsgLog.setMsgIndex(0)
ABCIMsgLog.setLog('')
const eventList1 = new StringEvent()
eventList1.setType('message')
const attribute1 = new Attribute()
attribute1.setKey('action')
attribute1.setValue('request')
eventList1.setAttributesList([attribute1])
const eventList2 = new StringEvent()
eventList2.setType('raw_request')
const attribute2 = new Attribute()
attribute2.setKey('data_source_id')
attribute2.setValue('61')
const attribute3 = new Attribute()
attribute3.setKey('data_source_hash')
attribute3.setValue(
'07be7bd61667327aae10b7a13a542c7dfba31b8f4c52b0b60bf9c7b11b1a72ef',
)
const attribute4 = new Attribute()
attribute4.setKey('external_id')
attribute4.setValue('6')
const attribute5 = new Attribute()
attribute5.setKey('calldata')
attribute5.setValue('ETH')
const attribute6 = new Attribute()
attribute6.setKey('fee')
attribute6.setValue('')
eventList2.setAttributesList([
attribute2,
attribute3,
attribute4,
attribute5,
attribute6,
])
const eventList3 = new StringEvent()
eventList3.setType('request')
const attribute7 = new Attribute()
attribute7.setKey('id')
attribute7.setValue('37643')
const attribute8 = new Attribute()
attribute8.setKey('client_id')
attribute8.setValue('Blue')
const attribute9 = new Attribute()
attribute9.setKey('oracle_script_id')
attribute9.setValue('37')
const attribute10 = new Attribute()
attribute10.setKey('calldata')
attribute10.setValue('00000001000000034554480000000000000064')
const attribute11 = new Attribute()
attribute11.setKey('ask_count')
attribute11.setValue('4')
const attribute12 = new Attribute()
attribute12.setKey('min_count')
attribute12.setValue('3')
const attribute13 = new Attribute()
attribute13.setKey('gas_used')
attribute13.setValue('71512')
const attribute14 = new Attribute()
attribute14.setKey('total_fees')
attribute14.setValue('')
const attribute15 = new Attribute()
attribute15.setKey('validator')
attribute15.setValue(
'bandvaloper19eu9g3gka6rxlevkjlvjq7s6c498tejnwxjwxx',
)
const attribute16 = new Attribute()
attribute16.setKey('validator')
attribute16.setValue(
'bandvaloper1p46uhvdk8vr829v747v85hst3mur2dzlhfemmz',
)
const attribute17 = new Attribute()
attribute17.setKey('validator')
attribute17.setValue(
'bandvaloper1a570h9e3rtvfhm030ta5hvel7e7e4lh4pgv8wj',
)
const attribute18 = new Attribute()
attribute18.setKey('validator')
attribute18.setValue(
'bandvaloper1274qgg28xkz6f3upx05ftr9zepgmtfgts392dy',
)
eventList3.setAttributesList([
attribute7,
attribute8,
attribute9,
attribute10,
attribute11,
attribute12,
attribute13,
attribute14,
attribute15,
attribute16,
attribute17,
attribute18,
])
ABCIMsgLog.setEventsList([eventList1, eventList2, eventList3])
txResponse.setInfo('')
txResponse.setGasWanted(2000000)
txResponse.setGasUsed(406535)
txResponse.setTimestamp('')
txResponse.setLogsList([ABCIMsgLog])
response.setTxResponse(txResponse)
callback(null, response)
return { cancel: function () {} }
},
)
const expected = {
height: 272796,
txhash:
'E894BB773470ADB28D8FA61BF5300A23D6BA04D2F28A6AF2E7DA5AB4122FA3E0',
codespace: '',
code: 0,
data: '0A090A0772657175657374',
eventsList: [],
rawLog:
'[{"events":[{"type":"message","attributes":[{"key":"action","value":"request"}]},{"type":"raw_request","attributes":[{"key":"data_source_id","value":"61"},{"key":"data_source_hash","value":"07be7bd61667327aae10b7a13a542c7dfba31b8f4c52b0b60bf9c7b11b1a72ef"},{"key":"external_id","value":"6"},{"key":"calldata","value":"ETH"},{"key":"fee"},{"key":"data_source_id","value":"57"},{"key":"data_source_hash","value":"61b369daa5c0918020a52165f6c7662d5b9c1eee915025cb3d2b9947a26e48c7"},{"key":"external_id","value":"0"},{"key":"calldata","value":"ETH"},{"key":"fee"},{"key":"data_source_id","value":"62"},{"key":"data_source_hash","value":"107048da9dbf7960c79fb20e0585e080bb9be07d42a1ce09c5479bbada8d0289"},{"key":"external_id","value":"3"},{"key":"calldata","value":"ETH"},{"key":"fee"},{"key":"data_source_id","value":"60"},{"key":"data_source_hash","value":"2e588de76a58338125022bc42b460072300aebbcc4acaf55f91755c1c1799bac"},{"key":"external_id","value":"5"},{"key":"calldata","value":"huobipro ETH"},{"key":"fee"},{"key":"data_source_id","value":"59"},{"key":"data_source_hash","value":"5c011454981c473af3bf6ef93c76b36bfb6cc0ce5310a70a1ba569de3fc0c15d"},{"key":"external_id","value":"2"},{"key":"calldata","value":"ETH"},{"key":"fee"},{"key":"data_source_id","value":"60"},{"key":"data_source_hash","value":"2e588de76a58338125022bc42b460072300aebbcc4acaf55f91755c1c1799bac"},{"key":"external_id","value":"4"},{"key":"calldata","value":"binance ETH"},{"key":"fee"},{"key":"data_source_id","value":"60"},{"key":"data_source_hash","value":"2e588de76a58338125022bc42b460072300aebbcc4acaf55f91755c1c1799bac"},{"key":"external_id","value":"9"},{"key":"calldata","value":"bittrex ETH"},{"key":"fee"},{"key":"data_source_id","value":"60"},{"key":"data_source_hash","value":"2e588de76a58338125022bc42b460072300aebbcc4acaf55f91755c1c1799bac"},{"key":"external_id","value":"7"},{"key":"calldata","value":"kraken ETH"},{"key":"fee"},{"key":"data_source_id","value":"60"},{"key":"data_source_hash","value":"2e588de76a58338125022bc42b460072300aebbcc4acaf55f91755c1c1799bac"},{"key":"external_id","value":"8"},{"key":"calldata","value":"bitfinex ETH"},{"key":"fee"},{"key":"data_source_id","value":"58"},{"key":"data_source_hash","value":"7e6759fade717a06fb643392bfde837bfc3437da2ded54feed706e6cd35de461"},{"key":"external_id","value":"1"},{"key":"calldata","value":"ETH"},{"key":"fee"}]},{"type":"request","attributes":[{"key":"id","value":"37643"},{"key":"client_id","value":"Blue"},{"key":"oracle_script_id","value":"37"},{"key":"calldata","value":"00000001000000034554480000000000000064"},{"key":"ask_count","value":"4"},{"key":"min_count","value":"3"},{"key":"gas_used","value":"71512"},{"key":"total_fees"},{"key":"validator","value":"bandvaloper19eu9g3gka6rxlevkjlvjq7s6c498tejnwxjwxx"},{"key":"validator","value":"bandvaloper1p46uhvdk8vr829v747v85hst3mur2dzlhfemmz"},{"key":"validator","value":"bandvaloper1a570h9e3rtvfhm030ta5hvel7e7e4lh4pgv8wj"},{"key":"validator","value":"bandvaloper1274qgg28xkz6f3upx05ftr9zepgmtfgts392dy"}]}]}]',
logsList: [
{
msgIndex: 0,
log: '',
eventsList: [
{
type: 'message',
attributesList: [
{
key: 'action',
value: 'request',
},
],
},
{
type: 'raw_request',
attributesList: [
{
key: 'data_source_id',
value: '61',
},
{
key: 'data_source_hash',
value:
'07be7bd61667327aae10b7a13a542c7dfba31b8f4c52b0b60bf9c7b11b1a72ef',
},
{
key: 'external_id',
value: '6',
},
{
key: 'calldata',
value: 'ETH',
},
{
key: 'fee',
value: '',
},
],
},
{
type: 'request',
attributesList: [
{
key: 'id',
value: '37643',
},
{
key: 'client_id',
value: 'Blue',
},
{
key: 'oracle_script_id',
value: '37',
},
{
key: 'calldata',
value: '00000001000000034554480000000000000064',
},
{
key: 'ask_count',
value: '4',
},
{
key: 'min_count',
value: '3',
},
{
key: 'gas_used',
value: '71512',
},
{
key: 'total_fees',
value: '',
},
{
key: 'validator',
value: 'bandvaloper19eu9g3gka6rxlevkjlvjq7s6c498tejnwxjwxx',
},
{
key: 'validator',
value: 'bandvaloper1p46uhvdk8vr829v747v85hst3mur2dzlhfemmz',
},
{
key: 'validator',
value: 'bandvaloper1a570h9e3rtvfhm030ta5hvel7e7e4lh4pgv8wj',
},
{
key: 'validator',
value: 'bandvaloper1274qgg28xkz6f3upx05ftr9zepgmtfgts392dy',
},
],
},
],
},
],
info: '',
gasWanted: 2000000,
gasUsed: 406535,
tx: undefined,
timestamp: '',
}
const response = await client.sendTxBlockMode('txBytes')
expect(mockedBroadcasting).toHaveBeenCalledTimes(1)
expect(response).toEqual(expected)
})
it('block mode signature fail', async () => {
expect(MockedTxService).not.toHaveBeenCalled()
const client = new Client(TEST_GRPC)
expect(MockedTxService).toHaveBeenCalledTimes(1)
const mockedTxServices = jest.mocked(MockedTxService.mock.instances[0])
type ExpectedDataSourceSignature = (
requestMessage: BroadcastTxRequest,
metadata: grpc.Metadata,
callback: (
error: ServiceError | null,
responseMessage: BroadcastTxResponse | null,
) => void,
) => UnaryResponse
const mockedBroadcasting = jest.mocked(
mockedTxServices.broadcastTx as ExpectedDataSourceSignature,
{
shallow: true,
},
)
mockedBroadcasting.mockImplementationOnce(
(_req, _metadata, callback): UnaryResponse => {
const response = new BroadcastTxResponse()
const txResponse = new TxResponse()
txResponse.setHeight(0)
txResponse.setCodespace('sdk')
txResponse.setCode(4)
txResponse.setTxhash(
'C6FCF7AB773EFE9D616DBD0C2B09CAF552C8998CABBF17A394B5243CAA9381E0',
)
txResponse.setRawLog(
'signature verification failed; please verify account number (104) and chain-id (band-laozi-testnet6): unauthorized',
),
txResponse.setGasWanted(2000000)
txResponse.setGasUsed(39362)
response.setTxResponse(txResponse)
callback(null, response)
return { cancel: function () {} }
},
)
expectedSignatureFailed
const response = await client.sendTxBlockMode('txBytesFail')
expect(mockedBroadcasting).toHaveBeenCalledTimes(1)
expect(response).toEqual(expectedSignatureFailed)
})
})