Skip to content

Commit

Permalink
refactor: sdk rhp
Browse files Browse the repository at this point in the history
  • Loading branch information
alexfreska committed Feb 29, 2024
1 parent 329d4a2 commit 09b68ae
Show file tree
Hide file tree
Showing 37 changed files with 911 additions and 500 deletions.
5 changes: 5 additions & 0 deletions .changeset/tiny-cougars-refuse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@siafoundation/sdk': minor
---

Updated SDK to latest core changes, updated structure.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module go.sia.tech/web

go 1.20

require go.sia.tech/core v0.2.2-0.20240229154321-d97c1d5b2172 // indirect
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
go.sia.tech/core v0.2.2-0.20240228221151-7c287b4d7782 h1:Wk+tqmEUM30E9fAJnNU0L5h+SGp8q7E8RW+13l3s9aY=
go.sia.tech/core v0.2.2-0.20240228221151-7c287b4d7782/go.mod h1:3EoY+rR78w1/uGoXXVqcYdwSjSJKuEMI5bL7WROA27Q=
go.sia.tech/core v0.2.2-0.20240229154321-d97c1d5b2172 h1:uET7VyK5mz02bsicyNeoEut/RarvmQXAvXgUqZ1YJoE=
go.sia.tech/core v0.2.2-0.20240229154321-d97c1d5b2172/go.mod h1:3EoY+rR78w1/uGoXXVqcYdwSjSJKuEMI5bL7WROA27Q=
2 changes: 1 addition & 1 deletion libs/sdk/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"cache": true,
"options": {
"commands": [
"tinygo build -o libs/sdk/src/wasm/resources/sdk.wasm -target wasm ./sdk"
"tinygo build -o libs/sdk/src/resources/sdk.wasm -target wasm ./sdk"
]
}
},
Expand Down
File renamed without changes.
285 changes: 285 additions & 0 deletions libs/sdk/src/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
import {
HostPrices,
HostSettings,
RPCReadSectorRequest,
RPCReadSectorResponse,
RPCSettingsResponse,
RPCWriteSectorRequest,
RPCWriteSectorResponse,
} from './types'
import { initSDKTest } from './initTest'

describe('wasm', () => {
it('generateAccoutID', async () => {
const sdk = await initSDKTest()
const { accountID } = sdk.wasm.generateAccountID()
expect(accountID).toBeDefined()
expect(accountID?.length).toBeGreaterThan(40)
})
describe('rhp', () => {
describe('settings', () => {
describe('request', () => {
it('valid', async () => {
const sdk = await initSDKTest()
const encode = sdk.wasm.rhp.encodeSettingsRequest()
expect(encode.rpc).toBeDefined()
expect(encode.error).not.toBeDefined()
if (!encode.rpc) {
throw new Error('rpc is undefined')
}
const decode = sdk.wasm.rhp.decodeSettingsRequest(encode.rpc)
expect(decode.data).toEqual({})
expect(decode.error).toEqual(undefined)
})
})
describe('response', () => {
it('valid', async () => {
const sdk = await initSDKTest()
const json = getSampleRPCSettingsResponse()
const encode = sdk.wasm.rhp.encodeSettingsResponse(json)
expect(encode.rpc).toBeDefined()
expect(encode.rpc?.length).toEqual(323)
expect(encode.error).toEqual(undefined)
if (!encode.rpc) {
throw new Error('rpc is undefined')
}
const decode = sdk.wasm.rhp.decodeSettingsResponse(encode.rpc)
expect(decode.data).toEqual(json)
expect(decode.error).toEqual(undefined)
})
it('encode error', async () => {
const sdk = await initSDKTest()
const json = {
settings: {
walletAddress: 'invalid',
},
} as RPCSettingsResponse
const encode = sdk.wasm.rhp.encodeSettingsResponse(json)
expect(encode.rpc).toEqual(undefined)
expect(encode.error).toEqual(
"decoding addr:<hex> failed: encoding/hex: invalid byte: U+0069 'i'"
)
})
it('decode error', async () => {
const sdk = await initSDKTest()
const json = getSampleRPCSettingsResponse()
const encode = sdk.wasm.rhp.encodeSettingsResponse(json)
if (!encode.rpc) {
throw new Error('rpc is undefined')
}
// manipulate the valid rpc to make it invalid
encode.rpc.set([1, 1], 30)
const decode = sdk.wasm.rhp.decodeSettingsResponse(encode.rpc)
expect(decode.data).not.toEqual(json)
expect(decode.error).toEqual(
'encoded object contains invalid length prefix (65806 elems > 11227 bytes left in stream)'
)
})
})
})
describe('read', () => {
describe('request', () => {
it('valid', async () => {
const sdk = await initSDKTest()
const json: RPCReadSectorRequest = {
token: {
account:
'acct:1b6793e900df020dc9a43c6df5f5d10dc5793956d44831ca5bbfec659021b75e',
validUntil: '2022-12-31T00:00:00-05:00',
signature:
'sig:457256d6a1603bef7fa957a70b5ba96a9def2fea8b4c1483060d7ba5cf8a072cfddf242a1ef033dd7d669c711e846c59cb916f804a03d72d279ffef7e6583404',
},
root: 'h:457256d6a1603bef7fa957a70b5ba96a9def2fea8b4c1483060d7ba5cf8a072c',
prices: getSampleHostPrices(),
offset: 0,
length: 4,
}
const encode = sdk.wasm.rhp.encodeReadSectorRequest(json)
expect(encode.rpc?.length).toEqual(312)
expect(encode.error).toEqual(undefined)
if (!encode.rpc) {
throw new Error('rpc is undefined')
}
const decode = sdk.wasm.rhp.decodeReadSectorRequest(encode.rpc)
expect(decode.data).toEqual(json)
expect(decode.error).toEqual(undefined)
})
it('encode error', async () => {
const sdk = await initSDKTest()
const json: RPCReadSectorRequest = {
token: {
account: 'invalid',
validUntil: '2022-12-31T00:00:00-05:00',
signature:
'sig:457256d6a1603bef7fa957a70b5ba96a9def2fea8b4c1483060d7ba5cf8a072cfddf242a1ef033dd7d669c711e846c59cb916f804a03d72d279ffef7e6583404',
},
root: 'h:457256d6a1603bef7fa957a70b5ba96a9def2fea8b4c1483060d7ba5cf8a072c',
prices: getSampleHostPrices(),
offset: 0,
length: 4,
}
const encode = sdk.wasm.rhp.encodeReadSectorRequest(json)
expect(encode.rpc).toEqual(undefined)
expect(encode.error).toEqual(
"decoding acct:<hex> failed: encoding/hex: invalid byte: U+0069 'i'"
)
})
})
describe('response', () => {
it('valid', async () => {
const sdk = await initSDKTest()
const json: RPCReadSectorResponse = {
proof: [
'h:457256d6a1603bef7fa957a70b5ba96a9def2fea8b4c1483060d7ba5cf8a072c',
],
sector: 'AQID',
}
const encode = sdk.wasm.rhp.encodeReadSectorResponse(json)
expect(encode.rpc?.toString()).toEqual(
[
0, 1, 0, 0, 0, 0, 0, 0, 0, 69, 114, 86, 214, 161, 96, 59, 239,
127, 169, 87, 167, 11, 91, 169, 106, 157, 239, 47, 234, 139, 76,
20, 131, 6, 13, 123, 165, 207, 138, 7, 44, 3, 0, 0, 0, 0, 0, 0, 0,
1, 2, 3,
].toString()
)
expect(encode.error).toEqual(undefined)
if (!encode.rpc) {
throw new Error('rpc is undefined')
}
const decode = sdk.wasm.rhp.decodeReadSectorResponse(encode.rpc)
expect(decode.data).toEqual(json)
expect(decode.error).toEqual(undefined)
})
it('encode error', async () => {
const sdk = await initSDKTest()
const json: RPCReadSectorResponse = {
proof: ['invalid'],
sector: 'AQID',
}
const encode = sdk.wasm.rhp.encodeReadSectorResponse(json)
expect(encode.rpc).toEqual(undefined)
expect(encode.error).toEqual(
'decoding h:<hex> failed: unexpected EOF'
)
})
})
})
describe('write', () => {
describe('request', () => {
it('valid', async () => {
const sdk = await initSDKTest()
const json: RPCWriteSectorRequest = {
token: {
account:
'acct:1b6793e900df020dc9a43c6df5f5d10dc5793956d44831ca5bbfec659021b75e',
validUntil: '2022-12-31T00:00:00-05:00',
signature:
'sig:457256d6a1603bef7fa957a70b5ba96a9def2fea8b4c1483060d7ba5cf8a072cfddf242a1ef033dd7d669c711e846c59cb916f804a03d72d279ffef7e6583404',
},
sector: 'AQID',
prices: getSampleHostPrices(),
}
const encode = sdk.wasm.rhp.encodeWriteSectorRequest(json)
expect(encode.rpc?.length).toEqual(275)
expect(encode.error).toEqual(undefined)
if (!encode.rpc) {
throw new Error('rpc is undefined')
}
const decode = sdk.wasm.rhp.decodeWriteSectorRequest(encode.rpc)
expect(decode.data).toEqual(json)
expect(decode.error).toEqual(undefined)
})
it('encode error', async () => {
const sdk = await initSDKTest()
const json = {
token: {
account: 'invalid',
validUntil: '2022-12-31T00:00:00-05:00',
signature:
'sig:457256d6a1603bef7fa957a70b5ba96a9def2fea8b4c1483060d7ba5cf8a072cfddf242a1ef033dd7d669c711e846c59cb916f804a03d72d279ffef7e6583404',
},
sector: 'AQID',
prices: getSampleHostPrices(),
} as RPCWriteSectorRequest
const encode = sdk.wasm.rhp.encodeWriteSectorRequest(json)
expect(encode.rpc).toEqual(undefined)
expect(encode.error).toEqual(
"decoding acct:<hex> failed: encoding/hex: invalid byte: U+0069 'i'"
)
})
})
describe('response', () => {
it('valid', async () => {
const sdk = await initSDKTest()
const json: RPCWriteSectorResponse = {
root: 'h:457256d6a1603bef7fa957a70b5ba96a9def2fea8b4c1483060d7ba5cf8a072c',
}
const encode = sdk.wasm.rhp.encodeWriteSectorResponse(json)
expect(encode.rpc?.toString()).toEqual(
[
0, 69, 114, 86, 214, 161, 96, 59, 239, 127, 169, 87, 167, 11, 91,
169, 106, 157, 239, 47, 234, 139, 76, 20, 131, 6, 13, 123, 165,
207, 138, 7, 44,
].toString()
)
expect(encode.error).toEqual(undefined)
if (!encode.rpc) {
throw new Error('rpc is undefined')
}
const decode = sdk.wasm.rhp.decodeWriteSectorResponse(encode.rpc)
expect(decode.data).toEqual(json)
expect(decode.error).toEqual(undefined)
})
it('encode error', async () => {
const sdk = await initSDKTest()
const json = {
root: 'invalid',
} as RPCWriteSectorResponse
const encode = sdk.wasm.rhp.encodeWriteSectorResponse(json)
expect(encode.rpc).toEqual(undefined)
expect(encode.error).toEqual(
'decoding h:<hex> failed: unexpected EOF'
)
})
})
})
})
})

function getSampleHostPrices(): HostPrices {
return {
contractPrice: '1000000000',
collateral: '2000000000',
storagePrice: '3000000000',
ingressPrice: '4000000000',
egressPrice: '5000000000',
tipHeight: 450_000,
validUntil: '2022-12-31T00:00:00-05:00',
signature:
'sig:457256d6a1603bef7fa957a70b5ba96a9def2fea8b4c1483060d7ba5cf8a072cfddf242a1ef033dd7d669c711e846c59cb916f804a03d72d279ffef7e6583404',
}
}

function getSampleRPCSettingsResponse(): RPCSettingsResponse {
const prices = getSampleHostPrices()
const settings: HostSettings = {
version: [1, 2, 3],
netAddresses: [
{ protocol: 'protocol1', address: 'address1longer' },
{ protocol: 'protocol2longer', address: 'address2' },
],
// 32 bytes
walletAddress:
'addr:eec8160897cf7058332040675d120c008dc32d96925e9b32a812b646e31676d7d52c118cad2c',
acceptingContracts: true,
maxCollateral: '1000000000',
maxDuration: 100,
remainingStorage: 100,
totalStorage: 100,
prices,
}
return {
settings,
}
}
2 changes: 1 addition & 1 deletion libs/sdk/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from './init'
export * from './types'
export * from './wasm'
7 changes: 7 additions & 0 deletions libs/sdk/src/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { getSDK } from './sdk'
import { initWASM } from './wasm'

export async function initSDK() {
await initWASM()
return getSDK()
}
7 changes: 7 additions & 0 deletions libs/sdk/src/initTest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { getSDK } from './sdk'
import { initWASMTest } from './wasmTest'

export async function initSDKTest() {
await initWASMTest()
return getSDK()
}
14 changes: 9 additions & 5 deletions libs/sdk/src/js/encoder.ts → libs/sdk/src/legacy/encoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,20 +90,24 @@ export function decodeString(d: Decoder): string {
return s
}

export function encodeCurrency(e: Encoder, c: bigint) {
export function encodeCurrency(e: Encoder, c: string) {
// currency is 128 bits, little endian
e.dataView.setBigUint64(e.offset, c & BigInt('0xFFFFFFFFFFFFFFFF'), true)
e.dataView.setBigUint64(
e.offset,
BigInt(c) & BigInt('0xFFFFFFFFFFFFFFFF'),
true
)
e.offset += 8
e.dataView.setBigUint64(e.offset, c >> BigInt(64), true)
e.dataView.setBigUint64(e.offset, BigInt(c) >> BigInt(64), true)
e.offset += 8
}

export function decodeCurrency(d: Decoder): bigint {
export function decodeCurrency(d: Decoder): string {
const lo = d.dataView.getBigUint64(d.offset, true)
d.offset += 8
const hi = d.dataView.getBigUint64(d.offset, true)
d.offset += 8
return (hi << BigInt(64)) | lo
return String((hi << BigInt(64)) | lo)
}

export function encodeAddress(e: Encoder, a: string) {
Expand Down
Loading

0 comments on commit 09b68ae

Please sign in to comment.