Skip to content

Commit

Permalink
Merge branch 'main' into custom-hrp
Browse files Browse the repository at this point in the history
  • Loading branch information
andreibancioiu committed May 27, 2024
2 parents 3480316 + 2f9d03a commit 734c042
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 38 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@multiversx/sdk-core",
"version": "13.2.0-beta.2",
"version": "13.2.0",
"description": "MultiversX SDK for JavaScript and TypeScript",
"main": "out/index.js",
"types": "out/index.d.js",
Expand Down
17 changes: 16 additions & 1 deletion src/smartcontracts/typesystem/abiRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,22 @@ const interfaceNamePlaceholder = "?";
export class AbiRegistry {
readonly name: string;
readonly constructorDefinition: EndpointDefinition;
readonly upgradeConstructorDefinition?: EndpointDefinition;
readonly endpoints: EndpointDefinition[] = [];
readonly customTypes: CustomType[] = [];
readonly events: EventDefinition[] = [];

private constructor(options: {
name: string;
constructorDefinition: EndpointDefinition;
upgradeConstructorDefinition?: EndpointDefinition;
endpoints: EndpointDefinition[];
customTypes: CustomType[];
events?: EventDefinition[];
}) {
this.name = options.name;
this.constructorDefinition = options.constructorDefinition;
this.upgradeConstructorDefinition = options.upgradeConstructorDefinition;
this.endpoints = options.endpoints;
this.customTypes = options.customTypes;
this.events = options.events || [];
Expand All @@ -33,18 +36,25 @@ export class AbiRegistry {
static create(options: {
name?: string;
constructor?: any;
upgradeConstructor?: any;
endpoints?: any[];
types?: Record<string, any>;
events?: any[];
}): AbiRegistry {
const name = options.name || interfaceNamePlaceholder;
const constructor = options.constructor || {};
const upgradeConstructor = options.upgradeConstructor || {};
const endpoints = options.endpoints || [];
const types = options.types || {};
const events = options.events || [];

// Load arbitrary input parameters into properly-defined objects (e.g. EndpointDefinition and CustomType).
const constructorDefinition = EndpointDefinition.fromJSON({ name: "constructor", ...constructor });
const upgradeConstructorDefinition = EndpointDefinition.fromJSON({
name: "upgradeConstructor",
...upgradeConstructor,
});

const endpointDefinitions = endpoints.map((item) => EndpointDefinition.fromJSON(item));
const customTypes: CustomType[] = [];

Expand All @@ -65,6 +75,7 @@ export class AbiRegistry {
const registry = new AbiRegistry({
name: name,
constructorDefinition: constructorDefinition,
upgradeConstructorDefinition: upgradeConstructorDefinition,
endpoints: endpointDefinitions,
customTypes: customTypes,
events: eventDefinitions,
Expand Down Expand Up @@ -139,8 +150,11 @@ export class AbiRegistry {
throw new errors.ErrTypingSystem("Did not re-map all custom types");
}

// Let's remap the constructor:
// Let's remap the constructor(s):
const newConstructor = mapEndpoint(this.constructorDefinition, mapper);
const newUpgradeConstructor = this.upgradeConstructorDefinition
? mapEndpoint(this.upgradeConstructorDefinition, mapper)
: undefined;

// Then, remap types of all endpoint parameters.
// The mapper learned all necessary types in the previous step.
Expand All @@ -156,6 +170,7 @@ export class AbiRegistry {
const newRegistry = new AbiRegistry({
name: this.name,
constructorDefinition: newConstructor,
upgradeConstructorDefinition: newUpgradeConstructor,
endpoints: newEndpoints,
customTypes: newCustomTypes,
events: newEvents,
Expand Down
39 changes: 16 additions & 23 deletions src/testdata/adder.abi.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
{
"buildInfo": {
"rustc": {
"version": "1.71.0-nightly",
"commitHash": "a2b1646c597329d0a25efa3889b66650f65de1de",
"commitDate": "2023-05-25",
"version": "1.76.0-nightly",
"commitHash": "d86d65bbc19b928387f68427fcc3a0da498d8a19",
"commitDate": "2023-12-10",
"channel": "Nightly",
"short": "rustc 1.71.0-nightly (a2b1646c5 2023-05-25)"
"short": "rustc 1.76.0-nightly (d86d65bbc 2023-12-10)"
},
"contractCrate": {
"name": "adder",
"version": "0.0.0",
"gitVersion": "v0.45.2.1-reproducible-169-g37d970c"
"gitVersion": "v0.50.1-3-gbed74682a"
},
"framework": {
"name": "multiversx-sc",
"version": "0.47.2"
"version": "0.50.1"
}
},
"docs": [
Expand All @@ -31,6 +31,15 @@
],
"outputs": []
},
"upgradeConstructor": {
"inputs": [
{
"name": "initial_value",
"type": "BigUint"
}
],
"outputs": []
},
"endpoints": [
{
"name": "getSum",
Expand All @@ -43,25 +52,9 @@
]
},
{
"name": "upgrade",
"mutability": "mutable",
"inputs": [
{
"name": "new_value",
"type": "BigUint"
}
],
"outputs": []
},
{
"docs": [
"Add desired amount to the storage variable."
],
"docs": ["Add desired amount to the storage variable."],
"name": "add",
"mutability": "mutable",
"payableInTokens": [
"*"
],
"inputs": [
{
"name": "value",
Expand Down
101 changes: 90 additions & 11 deletions src/transactionsFactories/smartContractTransactionsFactory.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,25 +347,104 @@ describe("test smart contract transactions factory", function () {
assert.deepEqual(transaction, transactionAbiAware);
});

it("should create 'Transaction' for upgrade, when ABI is available, but it doesn't contain a definition for 'upgrade'", async function () {
const abi = await loadAbiRegistry("src/testdata/adder.abi.json");
// Remove all endpoints (for the sake of the test).
abi.endpoints.length = 0;
it("should create 'Transaction' for upgrade, when ABI is available (with fallbacks)", async function () {
const abi = AbiRegistry.create({
upgradeConstructor: {
inputs: [
{
type: "u32",
},
{
type: "u32",
},
{
type: "u32",
},
],
},
endpoints: [
{
name: "upgrade",
inputs: [
{
type: "u32",
},
{
type: "u32",
},
],
},
],
constructor: {
inputs: [
{
type: "u32",
},
],
},
});

const factory = new SmartContractTransactionsFactory({
config: config,
abi: abi,
});

const transaction = factory.createTransactionForUpgrade({
sender: Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"),
contract: Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4"),
bytecode: adderByteCode.valueOf(),
gasLimit: 6000000n,
arguments: [new U32Value(7)],
const bytecode = Buffer.from("abba", "hex");
const sender = Address.fromBech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th");
const receiver = Address.fromBech32("erd1qqqqqqqqqqqqqpgqhy6nl6zq07rnzry8uyh6rtyq0uzgtk3e69fqgtz9l4");
const gasLimit = 6000000n;

// By default, use the upgrade constructor.
const tx1 = factory.createTransactionForUpgrade({
sender: sender,
contract: receiver,
bytecode: bytecode,
gasLimit: gasLimit,
arguments: [42, 42, 42],
});

assert.equal(Buffer.from(transaction.data!).toString(), `upgradeContract@${adderByteCode}@0504@07`);
assert.equal(Buffer.from(tx1.data!).toString(), `upgradeContract@abba@0504@2a@2a@2a`);

// Fallback to the "upgrade" endpoint.
(<any>abi).upgradeConstructorDefinition = undefined;

const tx2 = factory.createTransactionForUpgrade({
sender: sender,
contract: receiver,
bytecode: bytecode,
gasLimit: gasLimit,
arguments: [42, 42],
});

assert.equal(Buffer.from(tx2.data!).toString(), `upgradeContract@abba@0504@2a@2a`);

// Fallback to the constructor.
(<any>abi).endpoints.length = 0;

const tx3 = factory.createTransactionForUpgrade({
sender: sender,
contract: receiver,
bytecode: bytecode,
gasLimit: gasLimit,
arguments: [42],
});

assert.equal(Buffer.from(tx3.data!).toString(), `upgradeContract@abba@0504@2a`);

// No fallbacks.
(<any>abi).constructorDefinition = undefined;

assert.throws(
() =>
factory.createTransactionForUpgrade({
sender: sender,
contract: receiver,
bytecode: bytecode,
gasLimit: gasLimit,
arguments: [42],
}),
"Can't convert args to TypedValues",
);
});

it("should create 'Transaction' for claiming developer rewards", async function () {
Expand Down
5 changes: 5 additions & 0 deletions src/transactionsFactories/smartContractTransactionsFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ interface IConfig {

interface IAbi {
constructorDefinition: EndpointDefinition;
upgradeConstructorDefinition?: EndpointDefinition;

getEndpoint(name: string | ContractFunction): EndpointDefinition;
}
Expand Down Expand Up @@ -174,6 +175,10 @@ export class SmartContractTransactionsFactory {
return undefined;
}

if (this.abi.upgradeConstructorDefinition) {
return this.abi.upgradeConstructorDefinition;
}

try {
return this.abi.getEndpoint("upgrade");
} catch (error) {
Expand Down

0 comments on commit 734c042

Please sign in to comment.