Skip to content

Commit

Permalink
convert to jest, ts, add ci
Browse files Browse the repository at this point in the history
  • Loading branch information
fadeev committed Nov 17, 2024
1 parent 06c81bb commit 94759ee
Show file tree
Hide file tree
Showing 7 changed files with 2,204 additions and 575 deletions.
25 changes: 25 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Test

on:
pull_request:
branches: [main]

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout Repository
uses: actions/checkout@v3

- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "18"
registry-url: "https://registry.npmjs.org"

- name: Install Dependencies
run: yarn install

- name: Test
run: yarn test
5 changes: 5 additions & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
preset: "ts-jest",
testEnvironment: "node",
testMatch: ["**/?(*.)+(spec|test).ts?(x)"],
};
117 changes: 0 additions & 117 deletions memo.js

This file was deleted.

8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
"lint": "npm run lint:js && npm run lint:sol",
"docs": "rimraf docs && typedoc ./packages/client/src/index.ts",
"copy-templates": "npx cpx './packages/tasks/templates/**/*' ./dist/packages/tasks/templates",
"copy-types": "npx cpx './typechain-types/**/*' ./dist/typechain-types"
"copy-types": "npx cpx './typechain-types/**/*' ./dist/typechain-types",
"test": "yarn run jest"
},
"keywords": [],
"author": "ZetaChain",
Expand All @@ -46,6 +47,7 @@
"@typechain/hardhat": "^6.1.2",
"@types/chai": "^4.2.0",
"@types/isomorphic-fetch": "^0.0.38",
"@types/jest": "^29.5.14",
"@types/lodash": "^4.14.202",
"@types/mocha": ">=9.1.0",
"@types/node": ">=12.0.0",
Expand All @@ -67,12 +69,14 @@
"eslint-plugin-typescript-sort-keys": "^2.3.0",
"hardhat-gas-reporter": "^1.0.8",
"http-server": "^14.1.1",
"jest": "^29.7.0",
"prettier": "^2.8.8",
"prettier-plugin-solidity": "^1.1.3",
"rimraf": "^5.0.1",
"sinon": "^15.1.0",
"solhint": "^3.4.1",
"solidity-coverage": "^0.8.0",
"ts-jest": "^29.2.5",
"ts-node": ">=8.0.0",
"typechain": "^8.1.0",
"typedoc": "^0.26.5",
Expand Down Expand Up @@ -120,4 +124,4 @@
"ws": "^8.17.1"
},
"packageManager": "yarn@1.22.21+sha1.1959a18351b811cdeedbd484a8f86c3cc3bbaf72"
}
}
140 changes: 140 additions & 0 deletions packages/client/src/encodeToBytes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import { Web3 } from "web3";
import { ethers } from "ethers";
import { isAddress } from "web3-validator";

// Memo identifier byte
const MemoIdentifier = 0x5a;

// Enums
enum OpCode {
Deposit = 0b0000,
DepositAndCall = 0b0001,
Call = 0b0010,
Invalid = 0b0011,
}

enum EncodingFormat {
EncodingFmtABI = 0b0000,
EncodingFmtCompactShort = 0b0001,
EncodingFmtCompactLong = 0b0010,
}

// Header Class
class Header {
encodingFmt: EncodingFormat;
opCode: OpCode;

constructor(encodingFmt: EncodingFormat, opCode: OpCode) {
this.encodingFmt = encodingFmt;
this.opCode = opCode;
}
}

// FieldsV0 Class
class FieldsV0 {
receiver: string;
payload: Uint8Array;
revertAddress: string;

constructor(receiver: string, payload: Uint8Array, revertAddress: string) {
if (!isAddress(receiver)) {
throw new Error("Invalid receiver address");
}
this.receiver = receiver;
this.payload = payload;
this.revertAddress = revertAddress;
}
}

// Main Encoding Function
const encodeToBytes = (header: Header, fields: FieldsV0): Uint8Array => {
if (!header || !fields) {
throw new Error("Header and fields are required");
}

// Construct Header Bytes
const headerBytes = new Uint8Array(4);
headerBytes[0] = MemoIdentifier;
headerBytes[1] = (0x00 << 4) | (header.encodingFmt & 0x0f);
headerBytes[2] = ((header.opCode & 0x0f) << 4) | 0x00;
headerBytes[3] = 0b00000111;

// Encode Fields
let encodedFields: Uint8Array;
switch (header.encodingFmt) {
case EncodingFormat.EncodingFmtABI:
encodedFields = encodeFieldsABI(fields);
break;
case EncodingFormat.EncodingFmtCompactShort:
case EncodingFormat.EncodingFmtCompactLong:
encodedFields = encodeFieldsCompact(header.encodingFmt, fields);
break;
default:
throw new Error("Unsupported encoding format");
}

// Combine Header and Fields
return new Uint8Array(
Buffer.concat([Buffer.from(headerBytes), Buffer.from(encodedFields)])
);
};

// Helper: ABI Encoding
const encodeFieldsABI = (fields: FieldsV0): Uint8Array => {
const types = ["address", "bytes", "string"];
const values = [fields.receiver, fields.payload, fields.revertAddress];
const encodedData = ethers.utils.defaultAbiCoder.encode(types, values);
return Uint8Array.from(Buffer.from(encodedData.slice(2), "hex"));
};

// Helper: Compact Encoding
const encodeFieldsCompact = (
compactFmt: EncodingFormat,
fields: FieldsV0
): Uint8Array => {
const encodedReceiver = Buffer.from(Web3.utils.hexToBytes(fields.receiver));
const encodedPayload = encodeDataCompact(compactFmt, fields.payload);
const encodedRevertAddress = encodeDataCompact(
compactFmt,
new TextEncoder().encode(fields.revertAddress)
);

return new Uint8Array(
Buffer.concat([encodedReceiver, encodedPayload, encodedRevertAddress])
);
};

// Helper: Compact Data Encoding
const encodeDataCompact = (
compactFmt: EncodingFormat,
data: Uint8Array
): Uint8Array => {
const dataLen = data.length;
let encodedLength: Buffer;

switch (compactFmt) {
case EncodingFormat.EncodingFmtCompactShort:
if (dataLen > 255) {
throw new Error(
"Data length exceeds 255 bytes for EncodingFmtCompactShort"
);
}
encodedLength = Buffer.from([dataLen]);
break;
case EncodingFormat.EncodingFmtCompactLong:
if (dataLen > 65535) {
throw new Error(
"Data length exceeds 65535 bytes for EncodingFmtCompactLong"
);
}
encodedLength = Buffer.alloc(2);
encodedLength.writeUInt16LE(dataLen);
break;
default:
throw new Error("Unsupported compact format");
}

return Buffer.concat([encodedLength, data]);
};

export { Header, FieldsV0, EncodingFormat, OpCode, encodeToBytes };
Loading

0 comments on commit 94759ee

Please sign in to comment.