Add functionality to verify sender on reads
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "xrpio",
|
"name": "xrpio",
|
||||||
"version": "0.2.0",
|
"version": "0.2.1",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://gitea.nitowa.xyz/npm-packages/xrpio.git"
|
"url": "https://gitea.nitowa.xyz/npm-packages/xrpio.git"
|
||||||
|
|||||||
+2
-1
@@ -1 +1,2 @@
|
|||||||
export const ERR_BAD_TX_HASH = (hash:string) => new Error(`Bad tx hash format: "${hash}"`)
|
export const ERR_BAD_TX_HASH = (hash:string) => new Error(`Bad tx hash format: "${hash}"`)
|
||||||
|
export const ERR_NO_VERIFY_OWNER = (hash: string, actualAccount: string, desiredAccount: string) => new Error(`Expected tx "${hash}" to be initiated by ${desiredAccount} but was ${actualAccount}`)
|
||||||
@@ -4,7 +4,7 @@ import { Client, Payment, TxResponse, Wallet } from 'xrpl'
|
|||||||
import * as zlib from 'zlib'
|
import * as zlib from 'zlib'
|
||||||
import * as util from 'util'
|
import * as util from 'util'
|
||||||
import { NON_ZERO_TX_HASH } from '../util/protocol.constants'
|
import { NON_ZERO_TX_HASH } from '../util/protocol.constants'
|
||||||
import { ERR_BAD_TX_HASH } from '../util/errors'
|
import { ERR_BAD_TX_HASH, ERR_NO_VERIFY_OWNER } from '../util/errors'
|
||||||
|
|
||||||
const compressB64 = async (data: string) => (await util.promisify(zlib.deflate)(Buffer.from(data, 'utf-8'))).toString('base64')
|
const compressB64 = async (data: string) => (await util.promisify(zlib.deflate)(Buffer.from(data, 'utf-8'))).toString('base64')
|
||||||
const decompressB64 = async (data: string) => (await util.promisify(zlib.inflate)(Buffer.from(data, 'base64'))).toString('utf-8')
|
const decompressB64 = async (data: string) => (await util.promisify(zlib.inflate)(Buffer.from(data, 'base64'))).toString('utf-8')
|
||||||
@@ -125,13 +125,16 @@ export class xrpIO {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async readRaw(hash: string): Promise<Memo> {
|
public async readRaw(hash: string, verifyOwner?: string): Promise<Memo> {
|
||||||
|
|
||||||
if (!NON_ZERO_TX_HASH.test(hash)) {
|
if (!NON_ZERO_TX_HASH.test(hash)) {
|
||||||
throw ERR_BAD_TX_HASH(hash)
|
throw ERR_BAD_TX_HASH(hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
const tx = await this.getTransaction(hash)
|
const tx = await this.getTransaction(hash)
|
||||||
|
|
||||||
|
if(verifyOwner && tx.result.Account != verifyOwner){
|
||||||
|
throw ERR_NO_VERIFY_OWNER(hash, tx.result.Account, verifyOwner)
|
||||||
|
}
|
||||||
|
|
||||||
const memo = tx.result.Memos[0].Memo
|
const memo = tx.result.Memos[0].Memo
|
||||||
const memoParsed = {
|
const memoParsed = {
|
||||||
data: hexDecode(memo.MemoData),
|
data: hexDecode(memo.MemoData),
|
||||||
@@ -156,16 +159,16 @@ export class xrpIO {
|
|||||||
return await this.treeWrite(JSON.stringify(hashes), to, secret, 'N')
|
return await this.treeWrite(JSON.stringify(hashes), to, secret, 'N')
|
||||||
}
|
}
|
||||||
|
|
||||||
public async treeRead(hashes: string[]): Promise<string> {
|
public async treeRead(hashes: string[], verifyOwner?:string): Promise<string> {
|
||||||
const bad_hash = hashes.find(hash => !NON_ZERO_TX_HASH.test(hash))
|
const bad_hash = hashes.find(hash => !NON_ZERO_TX_HASH.test(hash))
|
||||||
if (bad_hash)
|
if (bad_hash)
|
||||||
throw ERR_BAD_TX_HASH(bad_hash)
|
throw ERR_BAD_TX_HASH(bad_hash)
|
||||||
|
|
||||||
const memos = await Promise.all(hashes.map(hash => this.readRaw(hash)))
|
const memos = await Promise.all(hashes.map(hash => this.readRaw(hash, verifyOwner)))
|
||||||
const payload: string = await decompressB64(memos.map(memo => memo.data).join(''))
|
const payload: string = await decompressB64(memos.map(memo => memo.data).join(''))
|
||||||
|
|
||||||
if (memos.some(memo => memo.format === 'N')) {
|
if (memos.some(memo => memo.format === 'N')) {
|
||||||
return await this.treeRead(JSON.parse(payload))
|
return await this.treeRead(JSON.parse(payload), verifyOwner)
|
||||||
}
|
}
|
||||||
|
|
||||||
return payload
|
return payload
|
||||||
|
|||||||
+32
-11
@@ -36,7 +36,6 @@ describe('XRPIO', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('getAccountSequence', async function(){
|
it('getAccountSequence', async function(){
|
||||||
//this.skip()
|
|
||||||
this.timeout(10000)
|
this.timeout(10000)
|
||||||
const seq = await api.getAccountSequence(sendWallet.address)
|
const seq = await api.getAccountSequence(sendWallet.address)
|
||||||
expect(seq).to.exist
|
expect(seq).to.exist
|
||||||
@@ -44,7 +43,7 @@ describe('XRPIO', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('estimateFee', async function () {
|
it('estimateFee', async function () {
|
||||||
this.timeout(2000)
|
this.timeout(10000)
|
||||||
const cost = await api.estimateFee(longText)
|
const cost = await api.estimateFee(longText)
|
||||||
expect(cost).to.be.a('number')
|
expect(cost).to.be.a('number')
|
||||||
expect(cost).to.be.lessThan(50)
|
expect(cost).to.be.lessThan(50)
|
||||||
@@ -53,7 +52,6 @@ describe('XRPIO', () => {
|
|||||||
|
|
||||||
let txHash
|
let txHash
|
||||||
it('writeRaw', async function(){
|
it('writeRaw', async function(){
|
||||||
//this.skip()
|
|
||||||
this.timeout(15000)
|
this.timeout(15000)
|
||||||
txHash = await api.writeRaw({data: TEST_DATA}, receiveWallet.address, sendWallet.secret);
|
txHash = await api.writeRaw({data: TEST_DATA}, receiveWallet.address, sendWallet.secret);
|
||||||
expect(txHash).to.exist
|
expect(txHash).to.exist
|
||||||
@@ -61,13 +59,26 @@ describe('XRPIO', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('readRaw', async function () {
|
it('readRaw', async function () {
|
||||||
//this.skip()
|
|
||||||
this.timeout(15000)
|
this.timeout(15000)
|
||||||
const memo = await api.readRaw(txHash)
|
const memo = await api.readRaw(txHash)
|
||||||
expect(memo).to.exist
|
expect(memo).to.exist
|
||||||
expect(memo.data).to.be.equal(TEST_DATA)
|
expect(memo.data).to.be.equal(TEST_DATA)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('verifyOwner readRaw', async function (){
|
||||||
|
this.timeout(15000)
|
||||||
|
const memo = await api.readRaw(txHash, sendWallet.address)
|
||||||
|
expect(memo).to.exist
|
||||||
|
expect(memo.data).to.be.equal(TEST_DATA)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('verifyOwner readRaw bad owner', function (done){
|
||||||
|
this.timeout(15000)
|
||||||
|
api.readRaw(txHash, "not the owner")
|
||||||
|
.then(_ => done(new Error('Expected error but succeeded')))
|
||||||
|
.catch(_ => done())
|
||||||
|
})
|
||||||
|
|
||||||
it('readRaw bad hash', function (done){
|
it('readRaw bad hash', function (done){
|
||||||
this.timeout(150000)
|
this.timeout(150000)
|
||||||
api.readRaw("123")
|
api.readRaw("123")
|
||||||
@@ -76,7 +87,6 @@ describe('XRPIO', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('treeWrite', async function(){
|
it('treeWrite', async function(){
|
||||||
// this.skip()
|
|
||||||
this.timeout(45000)
|
this.timeout(45000)
|
||||||
txHash = await api.treeWrite(longText, receiveWallet.address, sendWallet.secret)
|
txHash = await api.treeWrite(longText, receiveWallet.address, sendWallet.secret)
|
||||||
expect(txHash).to.exist
|
expect(txHash).to.exist
|
||||||
@@ -84,15 +94,27 @@ describe('XRPIO', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('treeRead', async function(){
|
it('treeRead', async function(){
|
||||||
// this.skip()
|
|
||||||
this.timeout(45000)
|
this.timeout(45000)
|
||||||
txHash = await api.treeRead([txHash])
|
const data = await api.treeRead([txHash])
|
||||||
expect(txHash).to.exist
|
expect(data).to.exist
|
||||||
expect(txHash).to.be.equal(longText)
|
expect(data).to.be.equal(longText)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('treeRead verify owner', async function(){
|
||||||
|
this.timeout(45000)
|
||||||
|
const data = await api.treeRead([txHash], sendWallet.address)
|
||||||
|
expect(data).to.exist
|
||||||
|
expect(data).to.be.equal(longText)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('verifyOwner treeRead bad owner', function(done){
|
||||||
|
this.timeout(45000)
|
||||||
|
api.treeRead([txHash], "not the owner")
|
||||||
|
.then(_ => done(new Error('Expected error but succeeded')))
|
||||||
|
.catch(_ => done())
|
||||||
})
|
})
|
||||||
|
|
||||||
it('treeWrite XL', async function(){
|
it('treeWrite XL', async function(){
|
||||||
//this.skip()
|
|
||||||
this.timeout(450000)
|
this.timeout(450000)
|
||||||
txHash = await api.treeWrite(htmlTxt, receiveWallet.address, sendWallet.secret)
|
txHash = await api.treeWrite(htmlTxt, receiveWallet.address, sendWallet.secret)
|
||||||
expect(txHash).to.exist
|
expect(txHash).to.exist
|
||||||
@@ -100,7 +122,6 @@ describe('XRPIO', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('treeRead XL', async function(){
|
it('treeRead XL', async function(){
|
||||||
//this.skip()
|
|
||||||
this.timeout(450000)
|
this.timeout(450000)
|
||||||
const data = await api.treeRead([txHash])
|
const data = await api.treeRead([txHash])
|
||||||
expect(data).to.exist
|
expect(data).to.exist
|
||||||
|
|||||||
Reference in New Issue
Block a user