Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dev into main #226

Merged
merged 11 commits into from
Oct 21, 2024
2 changes: 1 addition & 1 deletion xsuite-fullsimulnet-darwin-amd64/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@xsuite/full-simulnet-darwin-amd64",
"version": "0.0.14",
"version": "0.0.15",
"os": [
"darwin"
],
Expand Down
2 changes: 1 addition & 1 deletion xsuite-fullsimulnet-linux-amd64/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@xsuite/full-simulnet-linux-amd64",
"version": "0.0.14",
"version": "0.0.15",
"os": [
"linux"
],
Expand Down
2 changes: 1 addition & 1 deletion xsuite-fullsimulnet/build-binary.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ if (process.env.CI) {
]);
}

await $`GOBIN="$(pwd)" go install -ldflags ${argv.ldflags} github.com/multiversx/mx-chain-simulator-go/cmd/chainsimulator@v1.7.13-patch1-fix2`;
await $`GOBIN="$(pwd)" go install -ldflags ${argv.ldflags} github.com/multiversx/mx-chain-simulator-go/cmd/chainsimulator@v1.7.13-patch2-fix1`;
await $`mv ./chainsimulator ../xsuite-fullsimulnet-${argv.os}-${argv.arch}/bin/fsproxy`;
2 changes: 1 addition & 1 deletion xsuite-fullsimulnet/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@xsuite/full-simulnet",
"version": "0.0.14",
"version": "0.0.15",
"license": "MIT",
"scripts": {
"build": "run-script-os",
Expand Down
2 changes: 1 addition & 1 deletion xsuite/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "xsuite",
"version": "0.0.85",
"version": "0.0.88",
"license": "MIT",
"bin": {
"xsuite": "cli.js"
Expand Down
6 changes: 3 additions & 3 deletions xsuite/src/cli/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ test.concurrent(
"",
]);
},
100_000,
200_000,
);

test.concurrent(
Expand Down Expand Up @@ -469,7 +469,7 @@ test.concurrent(
"",
]);
},
100_000,
200_000,
);

test.concurrent("new contract | error: already exists", async () => {
Expand Down Expand Up @@ -505,7 +505,7 @@ test.concurrent(
"",
]);
},
180_000,
200_000,
);

test.concurrent("verify-reproducible", async () => {
Expand Down
74 changes: 42 additions & 32 deletions xsuite/src/data/encoding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,7 @@ export const e = {
return encodableVs.map(bytesLikeToHex);
},
kvs: Object.assign(
(encodableKvs: EncodableKvs): Kvs => {
const kvs = eKvsUnfiltered(encodableKvs);
for (const k in kvs) if (kvs[k] === "") delete kvs[k];
return kvs;
},
(encodableKvs: EncodableKvs) => filterKvs(eKvsUnfiltered(encodableKvs)),
{
Mapper: (...args: EncodableMapperKeyArgs) => ({
Value: curryEKvsMapper(eKvsMapperValue)(args),
Expand All @@ -232,34 +228,12 @@ export const e = {
Esdts: (esdts: EncodableEsdt[]) => eKvsEsdts(esdts),
},
),
account: <T extends EncodableAccount>(
encodableAccount: T,
): Prettify<PreserveDefinedness<T, Account>> => {
const account: Account = {
address: addressLikeToBechAddress(encodableAccount.address),
};
if (encodableAccount.nonce !== undefined) {
account.nonce = safeBigintToNumber(BigInt(encodableAccount.nonce));
}
if (encodableAccount.balance !== undefined) {
account.balance = encodableAccount.balance.toString();
}
if (encodableAccount.code !== undefined) {
account.code = encodableAccount.code;
}
if (encodableAccount.codeHash !== undefined) {
account.codeHash = encodableAccount.codeHash;
}
if (encodableAccount.codeMetadata !== undefined) {
account.codeMetadata = eCodeMetadata(encodableAccount.codeMetadata);
account: <T extends EncodableAccount>(encodableAccount: T) => {
const account = eAccountUnfiltered(encodableAccount);
if (account.kvs !== undefined) {
account.kvs = filterKvs(account.kvs);
}
if (encodableAccount.kvs !== undefined) {
account.kvs = e.kvs(encodableAccount.kvs);
}
if (encodableAccount.owner !== undefined) {
account.owner = addressLikeToBechAddress(encodableAccount.owner);
}
return account as PreserveDefinedness<T, Account>;
return account;
},
/**
* @deprecated Use `.TopBuffer` instead.
Expand Down Expand Up @@ -333,6 +307,12 @@ export const eKvsUnfiltered = (kvs: EncodableKvs): Kvs => {
}
};

const filterKvs = (unfilteredKvs: Kvs): Kvs => {
const kvs = { ...unfilteredKvs };
for (const k in kvs) if (kvs[k] === "") delete kvs[k];
return kvs;
};

const eKvsMappers = (mappers: EncodableMapper[]): Kvs => {
let kvs: Kvs = {};
for (const { key, ...rest } of mappers) {
Expand Down Expand Up @@ -573,6 +553,36 @@ export const eCodeMetadata = (codeMetadata: EncodableCodeMetadata): string => {
return e.Buffer(new Uint8Array(bytes)).toTopHex();
};

export const eAccountUnfiltered = <T extends EncodableAccount>(
encodableAccount: T,
): Prettify<PreserveDefinedness<T, Account>> => {
const account: Account = {
address: addressLikeToBechAddress(encodableAccount.address),
};
if (encodableAccount.nonce !== undefined) {
account.nonce = safeBigintToNumber(BigInt(encodableAccount.nonce));
}
if (encodableAccount.balance !== undefined) {
account.balance = encodableAccount.balance.toString();
}
if (encodableAccount.code !== undefined) {
account.code = encodableAccount.code;
}
if (encodableAccount.codeHash !== undefined) {
account.codeHash = encodableAccount.codeHash;
}
if (encodableAccount.codeMetadata !== undefined) {
account.codeMetadata = eCodeMetadata(encodableAccount.codeMetadata);
}
if (encodableAccount.kvs !== undefined) {
account.kvs = eKvsUnfiltered(encodableAccount.kvs);
}
if (encodableAccount.owner !== undefined) {
account.owner = addressLikeToBechAddress(encodableAccount.owner);
}
return account as PreserveDefinedness<T, Account>;
};

const newEncodable = (
toTop: () => Uint8Array,
toNest?: () => Uint8Array,
Expand Down
7 changes: 4 additions & 3 deletions xsuite/src/proxy/fsproxy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EncodableAccount, e } from "../data/encoding";
import { EncodableAccount, eAccountUnfiltered } from "../data/encoding";
import { hexToBase64 } from "../data/utils";
import { getValuesInOrder, Proxy } from "./proxy";

Expand Down Expand Up @@ -63,13 +63,14 @@ export class FSProxy extends Proxy {
}

const encodableAccountToSettableAccount = (account: EncodableAccount) => {
const { codeHash, codeMetadata, kvs, owner, ...rAcc } = e.account(account);
const { codeHash, codeMetadata, kvs, owner, ...rAcc } =
eAccountUnfiltered(account);
return {
...rAcc,
codeHash: codeHash !== undefined ? hexToBase64(codeHash) : undefined,
codeMetadata:
codeMetadata !== undefined ? hexToBase64(codeMetadata) : undefined,
keys: kvs !== undefined ? e.kvs(kvs) : undefined, // TODO-MvX: better if called "pairs"
keys: kvs, // TODO-MvX: better if called "pairs"
ownerAddress: owner,
};
};
6 changes: 3 additions & 3 deletions xsuite/src/proxy/lsproxy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { e, EncodableAccount } from "../data/encoding";
import { EncodableAccount, eAccountUnfiltered } from "../data/encoding";
import { getSerializableAccount, Proxy } from "./proxy";

export class LSProxy extends Proxy {
Expand All @@ -12,7 +12,7 @@ export class LSProxy extends Proxy {
setAccounts(accounts: EncodableAccount[]) {
return this.fetch(
"/admin/set-accounts",
accounts.map((a) => e.account(a)),
accounts.map((a) => eAccountUnfiltered(a)),
).then(() => {});
}

Expand All @@ -23,7 +23,7 @@ export class LSProxy extends Proxy {
updateAccounts(accounts: EncodableAccount[]) {
return this.fetch(
"/admin/update-accounts",
accounts.map((a) => e.account(a)),
accounts.map((a) => eAccountUnfiltered(a)),
).then(() => {});
}

Expand Down
56 changes: 56 additions & 0 deletions xsuite/src/proxy/proxy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import http from "node:http";
import { expect, test } from "vitest";
import { Proxy } from "./proxy";

test.concurrent("Proxy.fetchRaw - proxyUrl without path", async () => {
using server = await createServer();
const proxy = new Proxy(server.url);
const url = await proxy.fetchRaw("/request");
expect(url).toEqual(`${server.url}/request`);
});

test.concurrent("Proxy.fetchRaw - proxyUrl with non-empty path", async () => {
using server = await createServer();
const proxy = new Proxy(`${server.url}/path`);
const url = await proxy.fetchRaw("/request");
expect(url).toEqual(`${server.url}/path/request`);
});

test.concurrent("Proxy.fetchRaw - path not starting with slash", async () => {
using server = await createServer();
const proxy = new Proxy(`${server.url}/path`);
expect(() => proxy.fetchRaw(`${server.url}/request`)).toThrow(
"Invalid path.",
);
});

const createServer = async () => {
const server = http.createServer((req, res) => {
res.end(`"${getServerUrl(server)}${req.url}"`);
});

const url = await new Promise<string>((resolve) => {
server.listen(0, () => {
const address = server.address();
if (address === null || typeof address === "string") {
throw new Error("Invalid address.");
}
resolve(getServerUrl(server));
});
});

return {
url,
[Symbol.dispose]() {
server.close();
},
};
};

const getServerUrl = (server: http.Server) => {
const address = server.address();
if (address === null || typeof address === "string") {
throw new Error("Invalid address.");
}
return `http://localhost:${address.port}`;
};
45 changes: 25 additions & 20 deletions xsuite/src/proxy/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,14 @@ export class Proxy {
this.pauseAfterSend = params.pauseAfterSend;
}

private makeUrl(
path: string,
params: Record<string, { toString: () => string } | undefined> = {},
) {
const url = new URL(path, this.proxyUrl);
for (const [k, v] of Object.entries(params)) {
if (v !== undefined && v !== null) {
url.searchParams.set(k, v.toString());
}
}
return url.toString();
}

fetchRaw(path: string, data?: any) {
const init: RequestInit = { headers: this.headers };
if (data !== undefined) {
init.method = "POST";
init.body = JSON.stringify(data);
}
return fetch(
this.makeUrl(path, { blockNonce: this.blockNonce }),
this.proxyUrl + makePath(path, { blockNonce: this.blockNonce }),
init,
).then((r) => r.json());
}
Expand Down Expand Up @@ -333,7 +320,7 @@ export class Proxy {

private async _getTx(txHash: string, { withResults }: GetTxRawOptions = {}) {
const res = await this.fetch(
this.makeUrl(`/transaction/${txHash}`, { withResults }),
makePath(`/transaction/${txHash}`, { withResults }),
);
return res.transaction as Record<string, any>;
}
Expand All @@ -348,7 +335,7 @@ export class Proxy {
{ shardId }: GetAccountOptions = {},
) {
const res = await this.fetch(
this.makeUrl(`/address/${addressLikeToBechAddress(address)}/nonce`, {
makePath(`/address/${addressLikeToBechAddress(address)}/nonce`, {
"forced-shard-id": shardId,
}),
);
Expand All @@ -360,7 +347,7 @@ export class Proxy {
{ shardId }: GetAccountOptions = {},
) {
const res = await this.fetch(
this.makeUrl(`/address/${addressLikeToBechAddress(address)}/balance`, {
makePath(`/address/${addressLikeToBechAddress(address)}/balance`, {
"forced-shard-id": shardId,
}),
);
Expand All @@ -373,7 +360,7 @@ export class Proxy {
{ shardId }: GetAccountOptions = {},
): Promise<string> {
const res = await this.fetch(
this.makeUrl(
makePath(
`/address/${addressLikeToBechAddress(address)}/key/${bytesLikeToHex(
key,
)}`,
Expand All @@ -390,7 +377,7 @@ export class Proxy {
{ shardId }: GetAccountOptions = {},
) {
const res = await this.fetch(
this.makeUrl(`/address/${addressLikeToBechAddress(address)}/keys`, {
makePath(`/address/${addressLikeToBechAddress(address)}/keys`, {
"forced-shard-id": shardId,
}),
);
Expand All @@ -402,7 +389,7 @@ export class Proxy {
options?: GetAccountOptions,
) {
const res = await this.fetch(
this.makeUrl(`/address/${addressLikeToBechAddress(address)}`, options),
makePath(`/address/${addressLikeToBechAddress(address)}`, options),
);
return getSerializableAccount(res.account);
}
Expand Down Expand Up @@ -449,6 +436,24 @@ export class Proxy {
}
}

const makePath = (
path: string,
params: Record<string, { toString: () => string } | undefined> = {},
) => {
if (!path.startsWith("/")) {
throw new Error("Invalid path.");
}
const [basePath, existingQuery] = path.split("?");
const searchParams = new URLSearchParams(existingQuery);
for (const [k, v] of Object.entries(params)) {
if (v != null) {
searchParams.append(k, v.toString());
}
}
const newQuery = searchParams.toString();
return newQuery ? `${basePath}?${newQuery}` : basePath;
};

export class InteractionError extends Error {
interaction: string;
code: number | string;
Expand Down
Loading
Loading