diff --git a/src/rpc/response.ts b/src/rpc/response.ts index a5278e21f..c9b4a1ab2 100644 --- a/src/rpc/response.ts +++ b/src/rpc/response.ts @@ -320,6 +320,13 @@ export class InfoGetDeployResultV1Compatible { blockHeight?: number; public rawJSON: any; + + public static fromJSON( + json: any + ): InfoGetDeployResultV1Compatible | undefined { + const serializer = new TypedJSON(InfoGetDeployResultV1Compatible); + return serializer.parse(json); + } } @jsonObject diff --git a/src/types/Deploy.ts b/src/types/Deploy.ts index 2129e5e52..dc7552f65 100644 --- a/src/types/Deploy.ts +++ b/src/types/Deploy.ts @@ -19,7 +19,12 @@ import { ClassicMode, PricingMode } from './PricingMode'; import { TransactionTarget } from './TransactionTarget'; import { TransactionScheduling } from './TransactionScheduling'; import { ExecutableDeployItem } from './ExecutableDeployItem'; -import { byteHash, toBytesU32 } from './ByteConverters'; +import { + byteHash, + toBytesString, + toBytesU32, + toBytesU64 +} from './ByteConverters'; import { Conversions } from './Conversions'; /** @@ -143,52 +148,18 @@ export class DeployHeader { * @returns A `Uint8Array` representing the deploy header in byte format. */ public toBytes(): Uint8Array { - const accountBytes = this.account?.bytes() ?? new Uint8Array(); - const timestampBytes = new Uint8Array( - new BigUint64Array([BigInt(this.timestamp.toMilliseconds())]).buffer - ); - const ttlBytes = new Uint8Array( - new BigUint64Array([BigInt(this.ttl.toMilliseconds())]).buffer - ); - const gasPriceBytes = new Uint8Array( - new BigUint64Array([BigInt(this.gasPrice)]).buffer - ); - const bodyHashBytes = this.bodyHash?.toBytes() ?? new Uint8Array(); - const chainNameBytes = new TextEncoder().encode(this.chainName); - - const totalLength = - accountBytes.length + - timestampBytes.length + - ttlBytes.length + - gasPriceBytes.length + - bodyHashBytes.length + - chainNameBytes.length; - const result = new Uint8Array(totalLength); - - result.set(accountBytes, 0); - result.set(timestampBytes, accountBytes.length); - result.set(ttlBytes, accountBytes.length + timestampBytes.length); - result.set( - gasPriceBytes, - accountBytes.length + timestampBytes.length + ttlBytes.length - ); - result.set( - bodyHashBytes, - accountBytes.length + - timestampBytes.length + - ttlBytes.length + - gasPriceBytes.length - ); - result.set( - chainNameBytes, - accountBytes.length + - timestampBytes.length + - ttlBytes.length + - gasPriceBytes.length + - bodyHashBytes.length - ); + const dependenciesBytes = this.dependencies.map(e => e.toBytes()); + dependenciesBytes.splice(0, 0, toBytesU32(this.dependencies?.length)); - return result; + return concat([ + this.account!.bytes(), + toBytesU64(Date.parse(this.timestamp.toJSON())), + toBytesU64(this.ttl.duration), + toBytesU64(this.gasPrice), + this.bodyHash!.toBytes(), + concat(dependenciesBytes), + toBytesString(this.chainName) + ]); } /** diff --git a/src/types/Transaction.ts b/src/types/Transaction.ts index a6bbaeb63..8822a25b6 100644 --- a/src/types/Transaction.ts +++ b/src/types/Transaction.ts @@ -386,7 +386,7 @@ export class TransactionV1 { * Validates the transaction by checking the body hash and the approval signatures. * @throws {TransactionError} Throws errors if validation fails. */ - public validate(): void { + public validate(): boolean { const bodyBytes = this.body.toBytes(); if (!arrayEquals(byteHash(bodyBytes), this.header.bodyHash.toBytes())) @@ -407,6 +407,8 @@ export class TransactionV1 { throw ErrInvalidApprovalSignature; } } + + return true; } /** diff --git a/src/types/clvalue/Bool.test.ts b/src/types/clvalue/Bool.test.ts index 88b2e6118..afe9c65c8 100644 --- a/src/types/clvalue/Bool.test.ts +++ b/src/types/clvalue/Bool.test.ts @@ -13,10 +13,10 @@ describe('CLBool', () => { }); it('toBytes() / fromBytes() do proper bytes serialization', () => { - const myBool = CLValueBool.fromBoolean(false); - const myBool2 = CLValueBool.fromBoolean(true); - const myBoolBytes = CLValueParser.toBytesWithType(myBool); - const myBool2Bytes = CLValueParser.toBytesWithType(myBool2); + const myBool = new CLValueBool(false); + const myBool2 = new CLValueBool(true); + const myBoolBytes = myBool.bytes(); + const myBool2Bytes = myBool2.bytes(); const fromBytes1 = CLValueParser.fromBytesByType(myBoolBytes, CLTypeBool) .result; @@ -26,8 +26,8 @@ describe('CLBool', () => { expect(myBoolBytes).to.be.deep.eq(Uint8Array.from([0])); expect(myBool2Bytes).to.be.deep.eq(Uint8Array.from([1])); - expect(fromBytes1).to.be.deep.eq(myBool); - expect(fromBytes2).to.be.deep.eq(myBool2); + expect(fromBytes1.bool).to.be.deep.eq(myBool); + expect(fromBytes2.bool).to.be.deep.eq(myBool2); }); it('toJSON() / fromJSON() do proper bytes serialization', () => { diff --git a/src/types/clvalue/ByteArray.test.ts b/src/types/clvalue/ByteArray.test.ts index 6dcfd4974..15cb2059e 100644 --- a/src/types/clvalue/ByteArray.test.ts +++ b/src/types/clvalue/ByteArray.test.ts @@ -14,7 +14,7 @@ describe('CLByteArray', () => { it('Should be able to return proper byte array by calling toBytes() / fromBytes()', () => { const expectedBytes = Uint8Array.from(Array(32).fill(42)); const hash = CLValueByteArray.newCLByteArray(expectedBytes); - const bytes = CLValueParser.toBytesWithType(hash); + const bytes = hash.bytes(); expect(bytes).to.deep.eq(expectedBytes); expect( diff --git a/src/types/clvalue/Parser.ts b/src/types/clvalue/Parser.ts index 22b98f8f4..59785aa46 100644 --- a/src/types/clvalue/Parser.ts +++ b/src/types/clvalue/Parser.ts @@ -1,3 +1,5 @@ +import { concat } from '@ethersproject/bytes'; + import { CLValue, IResultWithBytes } from './CLValue'; import { Key, URef } from '../key'; import { PublicKey } from '../keypair'; @@ -35,6 +37,7 @@ import { CLValueTuple1 } from './Tuple1'; import { CLValueTuple2 } from './Tuple2'; import { CLValueTuple3 } from './Tuple3'; import { Conversions } from '../Conversions'; +import { toBytesArrayU8 } from '../ByteConverters'; /** * Error thrown when an unsupported CLType is encountered. @@ -85,7 +88,9 @@ export class CLValueParser { * @returns A Uint8Array containing the serialized CLValue with type information. */ static toBytesWithType(value: CLValue): Uint8Array { - return value.bytes(); + const clTypeBytes = value.getType().toBytes(); + const bytes = value.bytes(); + return concat([toBytesArrayU8(bytes), clTypeBytes]); } /** diff --git a/src/types/clvalue/String.test.ts b/src/types/clvalue/String.test.ts index 0fa9896a0..c280146f5 100644 --- a/src/types/clvalue/String.test.ts +++ b/src/types/clvalue/String.test.ts @@ -10,7 +10,7 @@ describe('CLString', () => { it('toBytes() / fromBytes()', () => { const str = CLValueString.newCLString('ABC'); - const bytes = CLValueParser.toBytesWithType(str); + const bytes = str.bytes(); const parsed = CLValueParser.fromBytesByType(bytes, str.type); expect(parsed.result).to.be.deep.eq(str); }); diff --git a/src/types/key/Uref.test.ts b/src/types/key/Uref.test.ts index a518e86d3..6afc577ad 100644 --- a/src/types/key/Uref.test.ts +++ b/src/types/key/Uref.test.ts @@ -39,7 +39,7 @@ describe('CLUref', () => { it('toBytes() / fromBytes() proper values', () => { const expectedBytes = Uint8Array.from([...Array(32).fill(42), 7]); const urefValue = CLValue.newCLUref(RWExampleURef); - const toBytes = CLValueParser.toBytesWithType(urefValue); + const toBytes = urefValue.bytes(); const fromBytes = CLValueParser.fromBytesByType( expectedBytes, urefValue.type