@roochnetwork/rooch-sdk
Version:
162 lines (140 loc) • 4.68 kB
text/typescript
// Copyright (c) RoochNetwork
// SPDX-License-Identifier: Apache-2.0
import { splitGenericParameters } from '@mysten/bcs'
import { concatBytes, isBytes, isHex, sha3_256, stringToBytes, toHEX } from '../utils/index.js'
import { canonicalRoochAddress, normalizeRoochAddress, RoochAddress } from '../address/index.js'
import { StructTag, TypeTag, BcsTypeTag } from './types.js'
import { address } from '../types/rooch.js'
import { Bytes } from '../types/bytes.js'
const VECTOR_REGEX = /^vector<(.+)>$/
const STRUCT_REGEX = /^([^:]+)::([^:]+)::([^<]+)(<(.+)>)?/
export class Serializer {
static structTagToObjectID(input: StructTag | string): string {
return `0x${toHEX(sha3_256(typeof input === 'string' ? input : Serializer.structTagToCanonicalString(input)))}`
}
//TODO: rooch Address bug
static accountNamedObjectID(address: address, structTag: StructTag | string) {
let addressBytes: Bytes
if (typeof address === 'string') {
const finalAddress = isHex(address) ? normalizeRoochAddress(address) : address
addressBytes = new RoochAddress(finalAddress).toBytes()
} else if (isBytes(address)) {
addressBytes = address
} else {
addressBytes = address.toBytes()
}
const tagBytes = stringToBytes(
'utf8',
typeof structTag === 'string' ? structTag : Serializer.structTagToCanonicalString(structTag),
)
return `0x${toHEX(sha3_256(concatBytes(addressBytes, tagBytes)))}`
}
static structTagToCanonicalString(input: StructTag): string {
let result = `${canonicalRoochAddress(input.address)}::${input.module}::${input.name}`
if (input.typeParams && input.typeParams.length > 0) {
const typeParams = input.typeParams.map(Serializer.typeTagToString).join(',')
result += `<${typeParams}>`
}
return result
}
static typeTagToString(input: TypeTag): string {
if (typeof input === 'string') {
return input
}
if ('Vector' in input) {
return `vector<${Serializer.typeTagToString(input.Vector)}>`
}
if ('Struct' in input) {
return Serializer.structTagToCanonicalString(input.Struct)
}
throw new Error('Invalid TypeTag')
}
static typeTagParseFromStr(str: string, normalizeAddress = false): BcsTypeTag {
if (str === 'address') {
return { address: null }
} else if (str === 'bool') {
return { bool: null }
} else if (str === 'u8') {
return { u8: null }
} else if (str === 'u16') {
return { u16: null }
} else if (str === 'u32') {
return { u32: null }
} else if (str === 'u64') {
return { u64: null }
} else if (str === 'u128') {
return { u128: null }
} else if (str === 'u256') {
return { u256: null }
} else if (str === 'signer') {
return { signer: null }
}
const vectorMatch = str.match(VECTOR_REGEX)
if (vectorMatch) {
return {
vector: Serializer.typeTagParseFromStr(vectorMatch[1], normalizeAddress),
}
}
const structMatch = str.match(STRUCT_REGEX)
if (structMatch) {
const address = normalizeAddress ? normalizeRoochAddress(structMatch[1]) : structMatch[1]
return {
struct: {
address,
module: structMatch[2],
name: structMatch[3],
typeParams:
structMatch[5] === undefined
? []
: Serializer.parseStructTypeArgs(structMatch[5], normalizeAddress),
},
}
}
throw new Error(`Encountered unexpected token when parsing type args for ${str}`)
}
static parseStructTypeArgs(str: string, normalizeAddress = false): BcsTypeTag[] {
return splitGenericParameters(str).map((tok) =>
Serializer.typeTagParseFromStr(tok, normalizeAddress),
)
}
static tagToString(tag: BcsTypeTag): string {
if ('bool' in tag) {
return 'bool'
}
if ('u8' in tag) {
return 'u8'
}
if ('u16' in tag) {
return 'u16'
}
if ('u32' in tag) {
return 'u32'
}
if ('u64' in tag) {
return 'u64'
}
if ('u128' in tag) {
return 'u128'
}
if ('u256' in tag) {
return 'u256'
}
if ('address' in tag) {
return 'address'
}
if ('signer' in tag) {
return 'signer'
}
if ('vector' in tag) {
return `vector<${Serializer.tagToString(tag.vector)}>`
}
if ('struct' in tag) {
const struct = tag.struct
const typeParams = struct.typeParams.map(Serializer.tagToString).join(', ')
return `${struct.address}::${struct.module}::${struct.name}${
typeParams ? `<${typeParams}>` : ''
}`
}
throw new Error('Invalid TypeTag')
}
}