genlayer-js 0.18.11 → 0.18.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -1
- package/.eslintignore +0 -3
- package/.eslintrc.cjs +0 -59
- package/.github/pull_request_template.md +0 -43
- package/.github/workflows/publish.yml +0 -98
- package/.github/workflows/smoke.yml +0 -27
- package/.github/workflows/test.yml +0 -33
- package/.prettierignore +0 -19
- package/.prettierrc +0 -12
- package/.release-it.json +0 -66
- package/CHANGELOG.md +0 -306
- package/CLAUDE.md +0 -66
- package/CONTRIBUTING.md +0 -87
- package/renovate.json +0 -20
- package/src/abi/calldata/consts.ts +0 -14
- package/src/abi/calldata/decoder.ts +0 -86
- package/src/abi/calldata/encoder.ts +0 -178
- package/src/abi/calldata/index.ts +0 -3
- package/src/abi/calldata/string.ts +0 -83
- package/src/abi/index.ts +0 -6
- package/src/abi/staking.ts +0 -1501
- package/src/abi/transactions.ts +0 -11
- package/src/accounts/IAccountActions.ts +0 -5
- package/src/accounts/account.ts +0 -9
- package/src/accounts/actions.ts +0 -34
- package/src/chains/actions.ts +0 -40
- package/src/chains/index.ts +0 -4
- package/src/chains/localnet.ts +0 -4016
- package/src/chains/studionet.ts +0 -4017
- package/src/chains/testnetAsimov.ts +0 -4013
- package/src/client/client.ts +0 -139
- package/src/config/snapID.ts +0 -4
- package/src/config/transactions.ts +0 -9
- package/src/contracts/actions.ts +0 -387
- package/src/global.d.ts +0 -9
- package/src/index.ts +0 -12
- package/src/staking/actions.ts +0 -690
- package/src/staking/index.ts +0 -2
- package/src/staking/utils.ts +0 -22
- package/src/transactions/ITransactionActions.ts +0 -15
- package/src/transactions/actions.ts +0 -113
- package/src/transactions/decoders.ts +0 -275
- package/src/types/accounts.ts +0 -1
- package/src/types/calldata.ts +0 -31
- package/src/types/chains.ts +0 -22
- package/src/types/clients.ts +0 -106
- package/src/types/contracts.ts +0 -32
- package/src/types/index.ts +0 -9
- package/src/types/metamaskClientResult.ts +0 -5
- package/src/types/network.ts +0 -1
- package/src/types/snapSource.ts +0 -1
- package/src/types/staking.ts +0 -220
- package/src/types/transactions.ts +0 -312
- package/src/utils/async.ts +0 -3
- package/src/utils/jsonifier.ts +0 -119
- package/src/wallet/actions.ts +0 -10
- package/src/wallet/connect.ts +0 -67
- package/src/wallet/metamaskClient.ts +0 -50
- package/tests/client.test-d.ts +0 -67
- package/tests/client.test.ts +0 -197
- package/tests/smoke.test.ts +0 -291
- package/tests/transactions.test.ts +0 -142
- package/tsconfig.json +0 -119
- package/tsconfig.vitest-temp.json +0 -41
- package/vitest.config.ts +0 -19
- package/vitest.smoke.config.ts +0 -16
package/CLAUDE.md
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
# CLAUDE.md
|
|
2
|
-
|
|
3
|
-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
-
|
|
5
|
-
## Build & Development
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install # Install dependencies
|
|
9
|
-
npm run build # Production build (tsup, outputs ESM+CJS to dist/)
|
|
10
|
-
npm run build:watch # Watch mode for development
|
|
11
|
-
npm run lint # ESLint with auto-fix
|
|
12
|
-
npm link # Link package locally for testing in other projects
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## Testing
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
npm test # Run tests with typecheck (vitest)
|
|
19
|
-
npm run test:watch # Watch mode
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## Architecture
|
|
23
|
-
|
|
24
|
-
### Module Structure & Exports
|
|
25
|
-
|
|
26
|
-
The SDK exports three entry points (see `package.json` exports):
|
|
27
|
-
- `genlayer-js` - Main: client, accounts, transaction decoders, staking utils
|
|
28
|
-
- `genlayer-js/chains` - Chain configs: `localnet`, `studionet`, `testnetAsimov`
|
|
29
|
-
- `genlayer-js/types` - TypeScript types for all SDK entities
|
|
30
|
-
|
|
31
|
-
### Client Factory Pattern
|
|
32
|
-
|
|
33
|
-
`createClient()` in `src/client/client.ts` builds a composable client by extending viem's base client with action modules:
|
|
34
|
-
|
|
35
|
-
```
|
|
36
|
-
baseClient → publicActions → walletActions → accountActions
|
|
37
|
-
→ transactionActions → chainActions → contractActions
|
|
38
|
-
→ receiptActions → stakingActions
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Each action module (`src/<domain>/actions.ts`) returns an object of methods that get merged into the client. The client auto-initializes the consensus smart contract on creation.
|
|
42
|
-
|
|
43
|
-
### Chain Configurations
|
|
44
|
-
|
|
45
|
-
`GenLayerChain` extends viem's `Chain` with GenLayer-specific properties:
|
|
46
|
-
- `isStudio` - Whether using studio-based localnet
|
|
47
|
-
- `consensusMainContract` / `consensusDataContract` - On-chain consensus contracts
|
|
48
|
-
- `stakingContract` - Staking contract (testnet-asimov only)
|
|
49
|
-
- `defaultNumberOfInitialValidators` / `defaultConsensusMaxRotations`
|
|
50
|
-
|
|
51
|
-
### Calldata Encoding
|
|
52
|
-
|
|
53
|
-
Custom binary encoding for GenLayer transactions in `src/abi/calldata/`:
|
|
54
|
-
- `encoder.ts` - Encodes JS values to GenLayer binary format
|
|
55
|
-
- `decoder.ts` - Decodes binary responses back to JS
|
|
56
|
-
- Uses MessagePack-like format with type tags
|
|
57
|
-
|
|
58
|
-
### Path Aliases
|
|
59
|
-
|
|
60
|
-
- `@/*` → `./src/*`
|
|
61
|
-
- `@@/tests/*` → `./tests/*`
|
|
62
|
-
|
|
63
|
-
### Key Dependencies
|
|
64
|
-
|
|
65
|
-
- `viem` - Ethereum client, used as foundation for all blockchain interactions
|
|
66
|
-
- `typescript-parsec` - Parser combinator for calldata string parsing
|
package/CONTRIBUTING.md
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
# Contributing to GenLayerJS SDK
|
|
2
|
-
|
|
3
|
-
We're thrilled that you're interested in contributing to the GenLayerJS SDK! This document will guide you through the contribution process.
|
|
4
|
-
|
|
5
|
-
## What is the GenLayerJS SDK?
|
|
6
|
-
|
|
7
|
-
The GenLayerJS SDK is a TypeScript library designed for developers building decentralized applications (Dapps) on the GenLayer protocol. It provides a comprehensive set of tools to interact with the GenLayer network, including client creation, transaction handling, event subscriptions, and more, all while leveraging the power of Viem as the underlying blockchain client.
|
|
8
|
-
|
|
9
|
-
## How You Can Contribute?
|
|
10
|
-
|
|
11
|
-
Contributions to the GenLayerJS SDK are welcome in several forms:
|
|
12
|
-
|
|
13
|
-
### Testing the SDK and Providing Feedback
|
|
14
|
-
|
|
15
|
-
Help us make the SDK better by testing and giving feedback:
|
|
16
|
-
|
|
17
|
-
- Start by installing the SDK in your Dapp using the command:
|
|
18
|
-
```sh
|
|
19
|
-
$ npm install genlayer-js
|
|
20
|
-
```
|
|
21
|
-
- Try out the SDK features and tell us what you think through our [feedback form](https://docs.google.com/forms/d/1IVNsZwm936kSNCiXmlAP8bgJnbik7Bqaoc3I6UYhr-o/viewform) or on our [Discord Channel](https://discord.gg/8Jm4v89VAu).
|
|
22
|
-
- If you find any issues, please report them on our [GitHub issues page](https://github.com/yeagerai/genlayer-js/issues).
|
|
23
|
-
|
|
24
|
-
### Sharing New Ideas and Use Cases
|
|
25
|
-
|
|
26
|
-
Have ideas for new features or use cases? We're eager to hear them! But first:
|
|
27
|
-
|
|
28
|
-
- Ensure you have the SDK installed to explore existing use cases.
|
|
29
|
-
- After familiarizing yourself with the SDK, contribute your unique use case and share your ideas in our [Discord channel](https://discord.gg/8Jm4v89VAu).
|
|
30
|
-
|
|
31
|
-
### Bug fixing and Feature development
|
|
32
|
-
|
|
33
|
-
#### 1. Set yourself up to start coding
|
|
34
|
-
|
|
35
|
-
- **1.1. Pick an issue**: Select one from the project GitHub repository [issue list](https://github.com/yeagerai/genlayer-js/issues) and assign it to yourself.
|
|
36
|
-
|
|
37
|
-
- **1.2. Create a branch**: create the branch that you will work on by using the link provided in the issue details page (right panel at the bottom - section "Development")
|
|
38
|
-
|
|
39
|
-
- **1.3. Setup the SDK locally**: clone the repository and install dependencies
|
|
40
|
-
|
|
41
|
-
```sh
|
|
42
|
-
$ git clone https://github.com/yeagerai/genlayer-js.git
|
|
43
|
-
$ cd genlayer-js
|
|
44
|
-
$ npm install
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
- **1.4. Run the SDK in dev mode**: to run the SDK in development mode with hot reload enabled:
|
|
48
|
-
|
|
49
|
-
```sh
|
|
50
|
-
$ npm run build:watch
|
|
51
|
-
```
|
|
52
|
-
- **1.5. Link the package locally**: to link the package locally, use the command:
|
|
53
|
-
|
|
54
|
-
```sh
|
|
55
|
-
$ npm link
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
This will allow you to use the package in your project without publishing it.
|
|
59
|
-
|
|
60
|
-
- **1.6. Add the package to your project**: to add the package to your project, use the command:
|
|
61
|
-
|
|
62
|
-
```sh
|
|
63
|
-
$ npm link genlayer-js
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
#### 2. Submit your solution
|
|
67
|
-
|
|
68
|
-
- **2.1. Prettier Formatter on Save File**: Configure IDE extensions to format your code with [Prettier](https://prettier.io/) before submitting it.
|
|
69
|
-
- **2.2. Code solution**: implement the solution in the code.
|
|
70
|
-
- **2.3. Pull Request**: Submit your changes through a pull request (PR). Fill the entire PR template and set the PR title as a valid conventional commit.
|
|
71
|
-
- **2.4. Check PR and issue linking**: if the issue and the PR are not linked, you can do it manually in the right panel of the Pull Request details page.
|
|
72
|
-
- **2.5. Peer Review**: One or more core contributors will review your PR. They may suggest changes or improvements.
|
|
73
|
-
- **2.6. Approval and Merge**: After approval from the reviewers, you can merge your PR with a squash and merge type of action.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
### Improving Documentation
|
|
77
|
-
|
|
78
|
-
To contribute to our docs, visit our [Documentation Repository](https://github.com/yeagerai/genlayer-docs) to create new issues or contribute to existing issues.
|
|
79
|
-
|
|
80
|
-
## Community
|
|
81
|
-
|
|
82
|
-
Connect with the GenLayer community to discuss, collaborate, and share insights:
|
|
83
|
-
|
|
84
|
-
- **[Discord Channel](https://discord.gg/8Jm4v89VAu)**: Our primary hub for discussions, support, and announcements.
|
|
85
|
-
- **[Telegram Group](https://t.me/genlayer)**: For more informal chats and quick updates.
|
|
86
|
-
|
|
87
|
-
Your continuous feedback drives better product development. Please engage with us regularly to test, discuss, and improve the GenLayerJS SDK.
|
package/renovate.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
|
3
|
-
"extends": ["config:recommended", "group:recommended", "group:allNonMajor", "group:githubArtifactActions"],
|
|
4
|
-
"packageRules": [
|
|
5
|
-
{
|
|
6
|
-
"matchUpdateTypes": ["minor", "patch", "pin", "digest"],
|
|
7
|
-
"automerge": true
|
|
8
|
-
}
|
|
9
|
-
],
|
|
10
|
-
"vulnerabilityAlerts": {
|
|
11
|
-
"enabled": true
|
|
12
|
-
},
|
|
13
|
-
"osvVulnerabilityAlerts": true,
|
|
14
|
-
"dependencyDashboard": true,
|
|
15
|
-
"npm": {
|
|
16
|
-
"minimumReleaseAge": "3 days"
|
|
17
|
-
},
|
|
18
|
-
"reviewers": ["denishacquin", "epsjunior", "cristiam86"],
|
|
19
|
-
"baseBranches": ["staging"]
|
|
20
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export const BITS_IN_TYPE = 3;
|
|
2
|
-
|
|
3
|
-
export const TYPE_SPECIAL = 0;
|
|
4
|
-
export const TYPE_PINT = 1;
|
|
5
|
-
export const TYPE_NINT = 2;
|
|
6
|
-
export const TYPE_BYTES = 3;
|
|
7
|
-
export const TYPE_STR = 4;
|
|
8
|
-
export const TYPE_ARR = 5;
|
|
9
|
-
export const TYPE_MAP = 6;
|
|
10
|
-
|
|
11
|
-
export const SPECIAL_NULL = (0 << BITS_IN_TYPE) | TYPE_SPECIAL;
|
|
12
|
-
export const SPECIAL_FALSE = (1 << BITS_IN_TYPE) | TYPE_SPECIAL;
|
|
13
|
-
export const SPECIAL_TRUE = (2 << BITS_IN_TYPE) | TYPE_SPECIAL;
|
|
14
|
-
export const SPECIAL_ADDR = (3 << BITS_IN_TYPE) | TYPE_SPECIAL;
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import type {CalldataEncodable} from "../../types/calldata";
|
|
2
|
-
import {CalldataAddress} from "../../types/calldata";
|
|
3
|
-
import * as consts from "./consts";
|
|
4
|
-
|
|
5
|
-
function readULeb128(data: Uint8Array, index: {i: number}): bigint {
|
|
6
|
-
let res: bigint = 0n;
|
|
7
|
-
let accum = 0n;
|
|
8
|
-
let shouldContinue = true;
|
|
9
|
-
while (shouldContinue) {
|
|
10
|
-
const byte = data[index.i];
|
|
11
|
-
index.i++;
|
|
12
|
-
const rest = byte & 0x7f;
|
|
13
|
-
res += BigInt(rest) * (1n << accum);
|
|
14
|
-
accum += 7n;
|
|
15
|
-
shouldContinue = byte >= 128;
|
|
16
|
-
}
|
|
17
|
-
return res;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function decodeImpl(data: Uint8Array, index: {i: number}): CalldataEncodable {
|
|
21
|
-
const cur = readULeb128(data, index);
|
|
22
|
-
switch (cur) {
|
|
23
|
-
case BigInt(consts.SPECIAL_NULL):
|
|
24
|
-
return null;
|
|
25
|
-
case BigInt(consts.SPECIAL_TRUE):
|
|
26
|
-
return true;
|
|
27
|
-
case BigInt(consts.SPECIAL_FALSE):
|
|
28
|
-
return false;
|
|
29
|
-
case BigInt(consts.SPECIAL_ADDR): {
|
|
30
|
-
const res = data.slice(index.i, index.i + 20);
|
|
31
|
-
index.i += 20;
|
|
32
|
-
return new CalldataAddress(res);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
const type = Number(cur & 0xffn) & ((1 << consts.BITS_IN_TYPE) - 1);
|
|
36
|
-
const rest = cur >> BigInt(consts.BITS_IN_TYPE);
|
|
37
|
-
switch (type) {
|
|
38
|
-
case consts.TYPE_BYTES: {
|
|
39
|
-
const ret = data.slice(index.i, index.i + Number(rest));
|
|
40
|
-
index.i += Number(rest);
|
|
41
|
-
return ret;
|
|
42
|
-
}
|
|
43
|
-
case consts.TYPE_PINT:
|
|
44
|
-
return rest;
|
|
45
|
-
case consts.TYPE_NINT:
|
|
46
|
-
return -1n - rest;
|
|
47
|
-
case consts.TYPE_STR: {
|
|
48
|
-
const ret = data.slice(index.i, index.i + Number(rest));
|
|
49
|
-
index.i += Number(rest);
|
|
50
|
-
return new TextDecoder("utf-8").decode(ret);
|
|
51
|
-
}
|
|
52
|
-
case consts.TYPE_ARR: {
|
|
53
|
-
const ret = [] as CalldataEncodable[];
|
|
54
|
-
let elems = rest;
|
|
55
|
-
while (elems > 0) {
|
|
56
|
-
elems--;
|
|
57
|
-
ret.push(decodeImpl(data, index));
|
|
58
|
-
}
|
|
59
|
-
return ret;
|
|
60
|
-
}
|
|
61
|
-
case consts.TYPE_MAP: {
|
|
62
|
-
const ret = new Map<string, CalldataEncodable>();
|
|
63
|
-
let elems = rest;
|
|
64
|
-
while (elems > 0) {
|
|
65
|
-
elems--;
|
|
66
|
-
const strLen = Number(readULeb128(data, index));
|
|
67
|
-
const key = data.slice(index.i, index.i + strLen);
|
|
68
|
-
index.i += strLen;
|
|
69
|
-
const keyStr = new TextDecoder("utf-8").decode(key);
|
|
70
|
-
ret.set(keyStr, decodeImpl(data, index));
|
|
71
|
-
}
|
|
72
|
-
return ret;
|
|
73
|
-
}
|
|
74
|
-
default:
|
|
75
|
-
throw new Error(`can't decode type from ${type} rest is ${rest} at pos ${index.i}`);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function decode(data: Uint8Array): CalldataEncodable {
|
|
80
|
-
const index = {i: 0};
|
|
81
|
-
const res = decodeImpl(data, index);
|
|
82
|
-
if (index.i !== data.length) {
|
|
83
|
-
throw new Error("some data left");
|
|
84
|
-
}
|
|
85
|
-
return res;
|
|
86
|
-
}
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
import type {CalldataEncodable} from "../../types/calldata";
|
|
2
|
-
import {CalldataAddress} from "../../types/calldata";
|
|
3
|
-
import * as consts from "./consts";
|
|
4
|
-
|
|
5
|
-
function reportError(msg: string, data: CalldataEncodable): never {
|
|
6
|
-
throw new Error(`invalid calldata input '${data}'`);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function writeNum(to: number[], data: bigint) {
|
|
10
|
-
if (data === 0n) {
|
|
11
|
-
to.push(0);
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
while (data > 0) {
|
|
15
|
-
let cur = Number(data & 0x7fn);
|
|
16
|
-
data >>= 7n;
|
|
17
|
-
if (data > 0) {
|
|
18
|
-
cur |= 0x80;
|
|
19
|
-
}
|
|
20
|
-
to.push(cur);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function encodeNumWithType(to: number[], data: bigint, type: number) {
|
|
25
|
-
const res = (data << BigInt(consts.BITS_IN_TYPE)) | BigInt(type);
|
|
26
|
-
writeNum(to, res);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function encodeNum(to: number[], data: bigint) {
|
|
30
|
-
if (data >= 0n) {
|
|
31
|
-
encodeNumWithType(to, data, consts.TYPE_PINT);
|
|
32
|
-
} else {
|
|
33
|
-
encodeNumWithType(to, -data - 1n, consts.TYPE_NINT);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function compareString(l: number[], r: number[]): number {
|
|
38
|
-
for (let index = 0; index < l.length && index < r.length; index++) {
|
|
39
|
-
const cur = l[index] - r[index];
|
|
40
|
-
if (cur !== 0) {
|
|
41
|
-
return cur;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return l.length - r.length;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function encodeMap(to: number[], arr: Iterable<[string, CalldataEncodable]>) {
|
|
48
|
-
// unicode code points array, utf8 encoded array, item
|
|
49
|
-
const newEntries: [number[], Uint8Array, CalldataEncodable][] = Array.from(
|
|
50
|
-
arr,
|
|
51
|
-
([k, v]): [number[], Uint8Array, CalldataEncodable] => [
|
|
52
|
-
Array.from(k, x => x.codePointAt(0)!),
|
|
53
|
-
new TextEncoder().encode(k),
|
|
54
|
-
v,
|
|
55
|
-
],
|
|
56
|
-
);
|
|
57
|
-
newEntries.sort((v1, v2) => compareString(v1[0], v2[0]));
|
|
58
|
-
for (let i = 1; i < newEntries.length; i++) {
|
|
59
|
-
if (compareString(newEntries[i - 1][0], newEntries[i][0]) === 0) {
|
|
60
|
-
throw new Error(`duplicate key '${new TextDecoder().decode(newEntries[i][1])}'`);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
encodeNumWithType(to, BigInt(newEntries.length), consts.TYPE_MAP);
|
|
65
|
-
for (const [, k, v] of newEntries) {
|
|
66
|
-
writeNum(to, BigInt(k.length));
|
|
67
|
-
for (const c of k) {
|
|
68
|
-
to.push(c);
|
|
69
|
-
}
|
|
70
|
-
encodeImpl(to, v);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function encodeImpl(to: number[], data: CalldataEncodable) {
|
|
75
|
-
if (data === null || data === undefined) {
|
|
76
|
-
to.push(consts.SPECIAL_NULL);
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
if (data === true) {
|
|
80
|
-
to.push(consts.SPECIAL_TRUE);
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
if (data === false) {
|
|
84
|
-
to.push(consts.SPECIAL_FALSE);
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
switch (typeof data) {
|
|
88
|
-
case "number": {
|
|
89
|
-
if (!Number.isInteger(data)) {
|
|
90
|
-
reportError("floats are not supported", data);
|
|
91
|
-
}
|
|
92
|
-
encodeNum(to, BigInt(data));
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
case "bigint": {
|
|
96
|
-
encodeNum(to, data);
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
case "string": {
|
|
100
|
-
const str = new TextEncoder().encode(data);
|
|
101
|
-
encodeNumWithType(to, BigInt(str.length), consts.TYPE_STR);
|
|
102
|
-
for (const c of str) {
|
|
103
|
-
to.push(c);
|
|
104
|
-
}
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
case "object": {
|
|
108
|
-
if (data instanceof Uint8Array) {
|
|
109
|
-
encodeNumWithType(to, BigInt(data.length), consts.TYPE_BYTES);
|
|
110
|
-
for (const c of data) {
|
|
111
|
-
to.push(c);
|
|
112
|
-
}
|
|
113
|
-
} else if (data instanceof Array) {
|
|
114
|
-
encodeNumWithType(to, BigInt(data.length), consts.TYPE_ARR);
|
|
115
|
-
for (const c of data) {
|
|
116
|
-
encodeImpl(to, c);
|
|
117
|
-
}
|
|
118
|
-
} else if (data instanceof Map) {
|
|
119
|
-
encodeMap(to, data);
|
|
120
|
-
} else if (data instanceof CalldataAddress) {
|
|
121
|
-
to.push(consts.SPECIAL_ADDR);
|
|
122
|
-
for (const c of data.bytes) {
|
|
123
|
-
to.push(c);
|
|
124
|
-
}
|
|
125
|
-
} else if (Object.getPrototypeOf(data) === Object.prototype) {
|
|
126
|
-
encodeMap(to, Object.entries(data));
|
|
127
|
-
} else {
|
|
128
|
-
reportError("unknown object type", data);
|
|
129
|
-
}
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
default:
|
|
133
|
-
reportError("unknown base type", data);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export function encode(data: CalldataEncodable): Uint8Array {
|
|
138
|
-
// FIXME: find a better growable type
|
|
139
|
-
const arr: number[] = [];
|
|
140
|
-
encodeImpl(arr, data);
|
|
141
|
-
return new Uint8Array(arr);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Constructs a calldata object for contract calls, omitting empty args/kwargs for compactness.
|
|
145
|
-
export function makeCalldataObject(
|
|
146
|
-
method: string | undefined,
|
|
147
|
-
args: CalldataEncodable[] | undefined,
|
|
148
|
-
kwargs: {[key: string]: CalldataEncodable} | Map<string, CalldataEncodable> | undefined,
|
|
149
|
-
): CalldataEncodable {
|
|
150
|
-
let ret: {[key: string]: CalldataEncodable} = {};
|
|
151
|
-
|
|
152
|
-
if (method) {
|
|
153
|
-
ret["method"] = method;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (args && args.length > 0) {
|
|
157
|
-
ret["args"] = args;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if (kwargs) {
|
|
161
|
-
if (kwargs instanceof Map) {
|
|
162
|
-
if (kwargs.size > 0) {
|
|
163
|
-
ret["kwargs"] = kwargs;
|
|
164
|
-
}
|
|
165
|
-
} else {
|
|
166
|
-
let hasVal = false;
|
|
167
|
-
for (const _k in kwargs) {
|
|
168
|
-
hasVal = true;
|
|
169
|
-
break;
|
|
170
|
-
}
|
|
171
|
-
if (hasVal) {
|
|
172
|
-
ret["kwargs"] = kwargs;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
return ret;
|
|
178
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import type {CalldataEncodable} from "../../types/calldata";
|
|
2
|
-
import {CalldataAddress} from "../../types/calldata";
|
|
3
|
-
|
|
4
|
-
function reportError(msg: string, data: CalldataEncodable): never {
|
|
5
|
-
throw new Error(`invalid calldata input '${data}'`);
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function toStringImplMap(data: Iterable<[string, CalldataEncodable]>, to: string[]) {
|
|
9
|
-
to.push("{");
|
|
10
|
-
for (const [k, v] of data) {
|
|
11
|
-
to.push(JSON.stringify(k));
|
|
12
|
-
to.push(":");
|
|
13
|
-
toStringImpl(v, to);
|
|
14
|
-
}
|
|
15
|
-
to.push("}");
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function toStringImpl(data: CalldataEncodable, to: string[]) {
|
|
19
|
-
if (data === null || data === undefined) {
|
|
20
|
-
to.push("null");
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
if (data === true) {
|
|
24
|
-
to.push("true");
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
if (data === false) {
|
|
28
|
-
to.push("false");
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
switch (typeof data) {
|
|
32
|
-
case "number": {
|
|
33
|
-
if (!Number.isInteger(data)) {
|
|
34
|
-
reportError("floats are not supported", data);
|
|
35
|
-
}
|
|
36
|
-
to.push(data.toString());
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
case "bigint": {
|
|
40
|
-
to.push(data.toString());
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
case "string": {
|
|
44
|
-
to.push(JSON.stringify(data));
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
case "object": {
|
|
48
|
-
if (data instanceof Uint8Array) {
|
|
49
|
-
to.push("b#");
|
|
50
|
-
for (const b of data) {
|
|
51
|
-
to.push(b.toString(16));
|
|
52
|
-
}
|
|
53
|
-
} else if (data instanceof Array) {
|
|
54
|
-
to.push("[");
|
|
55
|
-
for (const c of data) {
|
|
56
|
-
toStringImpl(c, to);
|
|
57
|
-
to.push(",");
|
|
58
|
-
}
|
|
59
|
-
to.push("]");
|
|
60
|
-
} else if (data instanceof Map) {
|
|
61
|
-
toStringImplMap(data.entries(), to);
|
|
62
|
-
} else if (data instanceof CalldataAddress) {
|
|
63
|
-
to.push("addr#");
|
|
64
|
-
for (const c of data.bytes) {
|
|
65
|
-
to.push(c.toString(16));
|
|
66
|
-
}
|
|
67
|
-
} else if (Object.getPrototypeOf(data) === Object.prototype) {
|
|
68
|
-
toStringImplMap(Object.entries(data), to);
|
|
69
|
-
} else {
|
|
70
|
-
reportError("unknown object type", data);
|
|
71
|
-
}
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
default:
|
|
75
|
-
reportError("unknown base type", data);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function toString(data: CalldataEncodable): string {
|
|
80
|
-
const to: string[] = [];
|
|
81
|
-
toStringImpl(data, to);
|
|
82
|
-
return to.join("");
|
|
83
|
-
}
|