Skip to content

Commit

Permalink
Merge pull request #487 from casper-ecosystem/CSDK-205-204-203
Browse files Browse the repository at this point in the history
Added new auction contract hash for integration-test network, fixed deserialization of CES schema, Update contract package parsing compatible 1.x, added unit tests to cover mentioned bugs / features
  • Loading branch information
Comp0te authored Jan 15, 2025
2 parents 05e9adc + 38c35b8 commit f107c00
Show file tree
Hide file tree
Showing 16 changed files with 1,125 additions and 329 deletions.
3 changes: 2 additions & 1 deletion src/@types/common.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export enum CasperNetworkName {
Mainnet = 'casper',
Testnet = 'casper-test'
Testnet = 'casper-test',
Integration = 'integration-test'
}

export enum AuctionManagerEntryPoint {
Expand Down
463 changes: 463 additions & 0 deletions src/rpc/rpc_client.test.ts

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions src/types/Contract.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { jsonArrayMember, jsonMember, jsonObject } from 'typedjson';
import { ContractHash, ContractPackageHash } from './key';
import { EntryPointV1 } from './EntryPoint';
import { NamedKeys } from './NamedKey';
import { NamedEntryPoint } from './AddressableEntity';

/**
* Represents a smart contract on the blockchain, including its unique identifiers, entry points, named keys, and protocol version.
Expand Down Expand Up @@ -33,8 +33,8 @@ export class Contract {
/**
* The list of entry points (functions) that can be called on this contract.
*/
@jsonArrayMember(EntryPointV1, { name: 'entry_points' })
entryPoints: EntryPointV1[];
@jsonArrayMember(NamedEntryPoint, { name: 'entry_points' })
entryPoints: NamedEntryPoint[];

/**
* The named keys associated with the contract, providing access to specific values or data stored by the contract.
Expand All @@ -59,7 +59,7 @@ export class Contract {
constructor(
contractPackageHash: ContractPackageHash,
contractWasmHash: ContractHash,
entryPoints: EntryPointV1[],
entryPoints: NamedEntryPoint[],
namedKeys: NamedKeys,
protocolVersion: string
) {
Expand Down
158 changes: 158 additions & 0 deletions src/types/ContractPackage.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import { TypedJSON } from 'typedjson';
import { expect } from 'chai';

import { ContractPackage } from './ContractPackage';

describe('ContractPackage', () => {
const createSerializerAndParse = (json: any) => {
const serializer = new TypedJSON(ContractPackage);
return serializer.parse(json);
};

const commonAssertions = (
contractPackage: ContractPackage | undefined,
json: any
) => {
expect(contractPackage?.accessKey.toPrefixedString()).to.deep.equal(
json.access_key
);
expect(contractPackage?.lockStatus).to.deep.equal(json.lock_status);
expect(contractPackage?.versions).to.not.be.empty;
expect(contractPackage?.groups).to.not.be.empty;

json.versions.forEach((version: any, index: number) => {
expect(
contractPackage?.versions[index].contractHash.toPrefixedString()
).to.deep.equal(version.contract_hash);
expect(contractPackage?.versions[index].contractVersion).to.deep.equal(
version.contract_version
);
expect(
contractPackage?.versions[index].protocolVersionMajor
).to.deep.equal(version.protocol_version_major);
});
};

it('should parse ContractPackage V1', () => {
const jsonV1 = {
access_key:
'uref-dc06bab1599b6163eab6786ca9a13e2ef28f157bd69a3bc3d8a4018a70450f8b-007',
versions: [
{
protocol_version_major: 1,
contract_version: 1,
contract_hash:
'contract-55cc25981545886d019401a40768adf71084ff4c251734b54280c3f1d600c9d1'
},
{
protocol_version_major: 1,
contract_version: 2,
contract_hash:
'contract-171f1bac4d4b12e66bdd1dfe2575c463b2e2ad8706cfa574b87ff5566b4c644c'
},
{
protocol_version_major: 1,
contract_version: 3,
contract_hash:
'contract-52809f5150e80b49096f25964082de4bcc3bdbb243d38414bbb22091a4ebdf96'
}
],
disabled_versions: [
{
protocol_version_major: 1,
contract_version: 1
},
{
protocol_version_major: 1,
contract_version: 2
}
],
groups: [
{
group: 'constructor',
keys: [
'uref-1ff80105947906fa593f18198825aab2033047253edf839b16f36ab949158d2b-007'
]
}
],
lock_status: 'Unlocked'
};

const contractPackage = createSerializerAndParse(jsonV1);
commonAssertions(contractPackage, jsonV1);

expect(contractPackage?.disabledVersions[0][0]).to.deep.equal(
jsonV1.disabled_versions[0].protocol_version_major
);
expect(contractPackage?.disabledVersions[0][1]).to.deep.equal(
jsonV1.disabled_versions[0].contract_version
);

jsonV1.groups.forEach((group, index: number) => {
expect(contractPackage?.groups[index].groupName).to.deep.equal(
group.group
);
expect(
contractPackage?.groups[index].groupUsers[0].toPrefixedString()
).to.deep.equal(group.keys?.[0]);
});
});

it('should parse ContractPackage V2', () => {
const jsonV2 = {
access_key:
'uref-dc06bab1599b6163eab6786ca9a13e2ef28f157bd69a3bc3d8a4018a70450f8b-007',
versions: [
{
protocol_version_major: 1,
contract_version: 1,
contract_hash:
'contract-55cc25981545886d019401a40768adf71084ff4c251734b54280c3f1d600c9d1'
},
{
protocol_version_major: 1,
contract_version: 2,
contract_hash:
'contract-171f1bac4d4b12e66bdd1dfe2575c463b2e2ad8706cfa574b87ff5566b4c644c'
},
{
protocol_version_major: 1,
contract_version: 3,
contract_hash:
'contract-52809f5150e80b49096f25964082de4bcc3bdbb243d38414bbb22091a4ebdf96'
}
],
disabled_versions: [
[1, 1],
[1, 2]
],
groups: [
{
group_name: 'constructor',
group_users: [
'uref-1ff80105947906fa593f18198825aab2033047253edf839b16f36ab949158d2b-007'
]
}
],
lock_status: 'Unlocked'
};

const contractPackage = createSerializerAndParse(jsonV2);
commonAssertions(contractPackage, jsonV2);

expect(contractPackage?.disabledVersions[0][0]).to.deep.equal(
jsonV2.disabled_versions[0][0]
);
expect(contractPackage?.disabledVersions[0][1]).to.deep.equal(
jsonV2.disabled_versions[0][1]
);
jsonV2.groups.forEach((group, index: number) => {
expect(contractPackage?.groups[index].groupName).to.deep.equal(
group.group_name
);
expect(
contractPackage?.groups[index].groupUsers[0].toPrefixedString()
).to.deep.equal(group.group_users?.[0]);
});
});
});
94 changes: 52 additions & 42 deletions src/types/ContractPackage.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,10 @@
import { jsonArrayMember, jsonMember, jsonObject } from 'typedjson';
import { jsonArrayMember, jsonMember, jsonObject, TypedJSON } from 'typedjson';
import { ContractHash, URef } from './key';
import { deserializeDisabledVersions } from './SerializationUtils';

/**
* Represents a disabled contract version, marking specific versions as incompatible with the current protocol.
*/
@jsonObject
class DisabledContractVersion {
/**
* The version number of the contract.
*/
@jsonMember({ name: 'contract_version', constructor: Number })
contractVersion: number;

/**
* Major version of the protocol that disables this contract version.
*/
@jsonMember({ name: 'protocol_version_major', constructor: Number })
protocolVersionMajor: number;

/**
* Constructs a new `DisabledContractVersion` instance.
* @param contractVersion - The version of the contract.
* @param protocolVersionMajor - The major protocol version disabling this contract version.
*/
constructor(contractVersion: number, protocolVersionMajor: number) {
this.contractVersion = contractVersion;
this.protocolVersionMajor = protocolVersionMajor;
}
export interface IDisabledVersion {
protocol_version_major: number;
contract_version: number;
}

/**
Expand All @@ -37,27 +15,46 @@ export class ContractGroup {
/**
* The name of the group.
*/
@jsonMember({ name: 'group', constructor: String })
group: string;
@jsonMember({ name: 'group_name', constructor: String, preserveNull: true })
groupName: string;

/**
* The list of URef keys associated with this group, defining permissions for contract interaction.
*/
@jsonArrayMember(URef, {
name: 'keys',
name: 'group_users',
serializer: (value: URef[]) => value.map(it => it.toJSON()),
deserializer: (json: any) => json.map((it: string) => URef.fromJSON(it))
deserializer: (json: any) => {
if (!json) return;
return json.map((it: string) => URef.fromJSON(it));
}
})
keys: URef[];
groupUsers: URef[];

/**
* Constructs a new `ContractGroup` instance.
* @param group - The name of the group.
* @param keys - An array of URef keys associated with the group.
* Converts a plain JSON object into an instance of `ContractGroup`.
*
* @param json The JSON object to parse.
* @returns An instance of `ContractGroup` or `undefined` if parsing fails.
*/
constructor(group: string, keys: URef[]) {
this.group = group;
this.keys = keys;
public static fromJSON(json: any): ContractGroup | undefined {
const serializer = new TypedJSON(ContractGroup);
const contractGroup = serializer.parse(json);

// V1 Compatible
if (contractGroup) {
if (Array.isArray(json?.keys)) {
contractGroup.groupUsers = json.keys.map((it: any) =>
URef.fromJSON(it)
);
}

if (typeof json?.group === 'string') {
contractGroup.groupName = json.group;
}
}

return contractGroup;
}
}

Expand Down Expand Up @@ -125,13 +122,26 @@ export class ContractPackage {
/**
* Array of disabled contract versions, marking incompatible versions.
*/
@jsonArrayMember(DisabledContractVersion, { name: 'disabled_versions' })
disabledVersions: DisabledContractVersion[];
@jsonArrayMember(Number, {
name: 'disabled_versions',
dimensions: 2,
deserializer: json => {
if (!json) return;
return deserializeDisabledVersions(json);
}
})
disabledVersions: number[][];

/**
* Array of contract groups, managing access control with sets of URef keys.
*/
@jsonArrayMember(ContractGroup, { name: 'groups' })
@jsonArrayMember(ContractGroup, {
name: 'groups',
deserializer: json => {
if (!json) return;
return json.map((it: ContractGroup) => ContractGroup.fromJSON(it));
}
})
groups: ContractGroup[];

/**
Expand All @@ -156,7 +166,7 @@ export class ContractPackage {
*/
constructor(
accessKey: URef,
disabledVersions: DisabledContractVersion[],
disabledVersions: number[][],
groups: ContractGroup[],
versions: ContractVersion[],
lockStatus: string
Expand Down
6 changes: 2 additions & 4 deletions src/types/Deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,7 @@ export class Deploy {
* @param keys The private key used to sign the deploy.
*/
public sign(keys: PrivateKey): void {
const signatureBytes = keys.signAndAddAlgorithmBytes(
this.hash.toBytes()
);
const signatureBytes = keys.signAndAddAlgorithmBytes(this.hash.toBytes());
const signature = new HexBytes(signatureBytes);
this.approvals.push(new Approval(keys.publicKey, signature));
}
Expand Down Expand Up @@ -412,7 +410,7 @@ export class Deploy {
deploy.session.getArgs(),
TransactionTarget.newTransactionTargetFromSession(deploy.session),
transactionEntryPoint,
new TransactionScheduling({ standard: {} }),
new TransactionScheduling({}), // Standard
deploy.approvals,
undefined,
deploy
Expand Down
3 changes: 1 addition & 2 deletions src/types/ExecutionResult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,8 +410,7 @@ export class ExecutionResult {
const transfer = new Transfer();
transfer.amount = writeTransfer.amount;
transfer.transactionHash = new TransactionHash(
undefined,
transform.key.transfer
writeTransfer?.deployHash
);
transfer.from = new InitiatorAddr(undefined, writeTransfer.from);
transfer.gas = writeTransfer.gas;
Expand Down
5 changes: 4 additions & 1 deletion src/types/Package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,10 @@ export class NamedUserGroup {
@jsonArrayMember(URef, {
name: 'group_users',
serializer: (value: URef[]) => value.map(it => it.toJSON()),
deserializer: (json: any) => json.map((it: string) => URef.fromJSON(it))
deserializer: (json: any) => {
if (!json) return;
return json.map((it: string) => URef.fromJSON(it));
}
})
groupUsers: URef[];

Expand Down
Loading

0 comments on commit f107c00

Please sign in to comment.