@mimicprotocol/lib-ts 0.0.1-rc.10
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/README.md +90 -0
- package/index.ts +8 -0
- package/package.json +26 -0
- package/src/chains/Arbitrum.ts +14 -0
- package/src/chains/Base.ts +14 -0
- package/src/chains/Ethereum.ts +12 -0
- package/src/chains/Gnosis.ts +14 -0
- package/src/chains/Optimism.ts +12 -0
- package/src/chains/index.ts +5 -0
- package/src/context/Context.ts +58 -0
- package/src/context/index.ts +1 -0
- package/src/environment.ts +115 -0
- package/src/evm.ts +40 -0
- package/src/helpers/constants.ts +9 -0
- package/src/helpers/index.ts +3 -0
- package/src/helpers/serialize.ts +14 -0
- package/src/helpers/strings.ts +103 -0
- package/src/intents/Call.ts +238 -0
- package/src/intents/Intent.ts +80 -0
- package/src/intents/Swap.ts +419 -0
- package/src/intents/Transfer.ts +349 -0
- package/src/intents/index.ts +4 -0
- package/src/log.ts +83 -0
- package/src/queries/Call.ts +27 -0
- package/src/queries/GetPrice.ts +28 -0
- package/src/queries/GetRelevantTokens.ts +82 -0
- package/src/queries/index.ts +3 -0
- package/src/tokens/Token.ts +169 -0
- package/src/tokens/TokenAmount.ts +222 -0
- package/src/tokens/USD.ts +201 -0
- package/src/tokens/index.ts +3 -0
- package/src/types/Address.ts +60 -0
- package/src/types/BigInt.ts +781 -0
- package/src/types/ByteArray.ts +316 -0
- package/src/types/Bytes.ts +137 -0
- package/src/types/ChainId.ts +11 -0
- package/src/types/EvmDecodeParam.ts +7 -0
- package/src/types/EvmEncodeParam.ts +31 -0
- package/src/types/index.ts +10 -0
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<h1 align="center">
|
|
2
|
+
<a href="https://mimic.fi"><img src="https://www.mimic.fi/logo.png" alt="Mimic Protocol" width="200"></a>
|
|
3
|
+
</h1>
|
|
4
|
+
|
|
5
|
+
<h4 align="center">Blockchain automation protocol</h4>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://github.com/mimic-protocol/tooling/actions/workflows/ci.yml">
|
|
9
|
+
<img src="https://github.com/mimic-protocol/tooling/actions/workflows/ci.yml/badge.svg" alt="Build">
|
|
10
|
+
</a>
|
|
11
|
+
<a href="https://discord.mimic.fi">
|
|
12
|
+
<img alt="Discord" src="https://img.shields.io/discord/989984112397922325">
|
|
13
|
+
</a>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<a href="#content">Content</a> •
|
|
18
|
+
<a href="#setup">Setup</a> •
|
|
19
|
+
<a href="#usage">Usage</a> •
|
|
20
|
+
<a href="#security">Security</a> •
|
|
21
|
+
<a href="#license">License</a>
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Content
|
|
27
|
+
|
|
28
|
+
This package provides a lightweight standard library for writing Mimic Protocol tasks in AssemblyScript. It includes:
|
|
29
|
+
|
|
30
|
+
- Typed primitives to interact with oracles and contracts
|
|
31
|
+
- Safe and minimal bindings for blockchain-specific operations
|
|
32
|
+
- Utility helpers for developing deterministic, deployable task logic
|
|
33
|
+
|
|
34
|
+
## Setup
|
|
35
|
+
|
|
36
|
+
To set up this project you'll need [git](https://git-scm.com) and [yarn](https://classic.yarnpkg.com) installed.
|
|
37
|
+
|
|
38
|
+
Install the library from the root of the monorepo:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Clone this repository
|
|
42
|
+
$ git clone https://github.com/mimic-protocol/tooling
|
|
43
|
+
|
|
44
|
+
# Go into the repository
|
|
45
|
+
$ cd tooling
|
|
46
|
+
|
|
47
|
+
# Install dependencies
|
|
48
|
+
$ yarn
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Usage
|
|
52
|
+
|
|
53
|
+
Here’s an example of how to use the library in a Mimic task:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { environment, Token } from '@mimicprotocol/lib-ts'
|
|
57
|
+
|
|
58
|
+
const USDC = Token.fromString('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', 1)
|
|
59
|
+
|
|
60
|
+
environment.getPrice(USDC, new Date(1744818017000))
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
For full task development guide and examples please visit [docs.mimic.fi](https://docs.mimic.fi/)
|
|
64
|
+
|
|
65
|
+
## Security
|
|
66
|
+
|
|
67
|
+
To read more about our auditing and related security processes please refer to the [security section](https://docs.mimic.fi/miscellaneous/security) of our docs site.
|
|
68
|
+
|
|
69
|
+
However, if you found any potential issue in any of our smart contracts or in any piece of code you consider critical
|
|
70
|
+
for the safety of the protocol, please contact us through <a href="mailto:security@mimic.fi">security@mimic.fi</a>.
|
|
71
|
+
|
|
72
|
+
## License
|
|
73
|
+
|
|
74
|
+
This project is licensed under the GNU General Public License v3.0.
|
|
75
|
+
See the [LICENSE](../../LICENSE) file for details.
|
|
76
|
+
|
|
77
|
+
### Third-Party Code
|
|
78
|
+
|
|
79
|
+
This project includes code from [The Graph Tooling](https://github.com/graphprotocol/graph-tooling), licensed under the MIT License.
|
|
80
|
+
See the [LICENSE-MIT](https://github.com/graphprotocol/graph-tooling/blob/27659e56adfa3ef395ceaf39053dc4a31e6d86b7/LICENSE-MIT) file for details.
|
|
81
|
+
Their original license and attribution are preserved.
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
> Website [mimic.fi](https://mimic.fi) ·
|
|
87
|
+
> Docs [docs.mimic.fi](https://docs.mimic.fi) ·
|
|
88
|
+
> GitHub [@mimic-fi](https://github.com/mimic-fi) ·
|
|
89
|
+
> Twitter [@mimicfi](https://twitter.com/mimicfi) ·
|
|
90
|
+
> Discord [mimic](https://discord.mimic.fi)
|
package/index.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mimicprotocol/lib-ts",
|
|
3
|
+
"version": "0.0.1-rc.10",
|
|
4
|
+
"license": "GPL-3.0",
|
|
5
|
+
"private": false,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "asc index.ts -b build/lib.wasm --disableWarning 235 --noEmit --transform json-as/transform",
|
|
9
|
+
"test": "asp",
|
|
10
|
+
"lint": "eslint . --ignore-pattern 'src/environment.ts' --ignore-pattern 'src/evm.ts' --ignore-pattern 'src/log.ts'"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"src",
|
|
14
|
+
"index.ts",
|
|
15
|
+
"asconfig.json"
|
|
16
|
+
],
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@as-pect/cli": "8.1.0",
|
|
19
|
+
"assemblyscript": "0.27.36"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"eslint-config-mimic": "^0.0.3",
|
|
23
|
+
"json-as": "1.1.7",
|
|
24
|
+
"visitor-as": "0.11.4"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Token } from '../tokens'
|
|
2
|
+
import { ChainId } from '../types'
|
|
3
|
+
|
|
4
|
+
/* eslint-disable no-secrets/no-secrets */
|
|
5
|
+
|
|
6
|
+
export namespace Arbitrum {
|
|
7
|
+
export const CHAIN_ID = ChainId.ARBITRUM
|
|
8
|
+
export const ETH = Token.native(CHAIN_ID)
|
|
9
|
+
export const USDC = Token.fromString('0xaf88d065e77c8cC2239327C5EDb3A432268e5831', CHAIN_ID, 6, 'USDC')
|
|
10
|
+
export const USDT = Token.fromString('0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9', CHAIN_ID, 6, 'USDT')
|
|
11
|
+
export const DAI = Token.fromString('0xda10009cbd5d07dd0cecc66161fc93d7c9000da1', CHAIN_ID, 18, 'DAI')
|
|
12
|
+
export const WBTC = Token.fromString('0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f', CHAIN_ID, 8, 'WBTC')
|
|
13
|
+
export const WETH = Token.fromString('0x82af49447d8a07e3bd95bd0d56f35241523fbab1', CHAIN_ID, 18, 'WETH')
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Token } from '../tokens'
|
|
2
|
+
import { ChainId } from '../types'
|
|
3
|
+
|
|
4
|
+
/* eslint-disable no-secrets/no-secrets */
|
|
5
|
+
|
|
6
|
+
export namespace Base {
|
|
7
|
+
export const CHAIN_ID = ChainId.BASE
|
|
8
|
+
export const ETH = Token.native(CHAIN_ID)
|
|
9
|
+
export const USDC = Token.fromString('0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', CHAIN_ID, 6, 'USDC')
|
|
10
|
+
export const USDT = Token.fromString('0xfde4c96c8593536e31f229ea8f37b2ada2699bb2', CHAIN_ID, 6, 'USDT')
|
|
11
|
+
export const DAI = Token.fromString('0x50c5725949a6f0c72e6c4a641f24049a917db0cb', CHAIN_ID, 18, 'DAI')
|
|
12
|
+
export const WBTC = Token.fromString('0x0555e30da8f98308edb960aa94c0db47230d2b9c', CHAIN_ID, 8, 'WBTC')
|
|
13
|
+
export const WETH = Token.fromString('0x4200000000000000000000000000000000000006', CHAIN_ID, 18, 'WETH')
|
|
14
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Token } from '../tokens'
|
|
2
|
+
import { ChainId } from '../types'
|
|
3
|
+
|
|
4
|
+
export namespace Ethereum {
|
|
5
|
+
export const CHAIN_ID = ChainId.ETHEREUM
|
|
6
|
+
export const ETH = Token.native(CHAIN_ID)
|
|
7
|
+
export const USDC = Token.fromString('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', CHAIN_ID, 6, 'USDC')
|
|
8
|
+
export const USDT = Token.fromString('0xdac17f958d2ee523a2206206994597c13d831ec7', CHAIN_ID, 6, 'USDT')
|
|
9
|
+
export const DAI = Token.fromString('0x6b175474e89094c44da98b954eedeac495271d0f', CHAIN_ID, 18, 'DAI')
|
|
10
|
+
export const WBTC = Token.fromString('0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', CHAIN_ID, 8, 'WBTC')
|
|
11
|
+
export const WETH = Token.fromString('0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', CHAIN_ID, 18, 'WETH')
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Token } from '../tokens'
|
|
2
|
+
import { ChainId } from '../types'
|
|
3
|
+
|
|
4
|
+
/* eslint-disable no-secrets/no-secrets */
|
|
5
|
+
|
|
6
|
+
export namespace Gnosis {
|
|
7
|
+
export const CHAIN_ID = ChainId.GNOSIS
|
|
8
|
+
export const xDAI = Token.native(CHAIN_ID)
|
|
9
|
+
export const USDC = Token.fromString('0x2a22f9c3b484c3629090feed35f17ff8f88f76f0', CHAIN_ID, 6, 'USDC')
|
|
10
|
+
export const USDT = Token.fromString('0x4ecaba5870353805a9f068101a40e0f32ed605c6', CHAIN_ID, 6, 'USDT')
|
|
11
|
+
export const WXDAI = Token.fromString('0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d', CHAIN_ID, 18, 'WXDAI')
|
|
12
|
+
export const WBTC = Token.fromString('0x8e5bbbb09ed1ebde8674cda39a0c169401db4252', CHAIN_ID, 8, 'WBTC')
|
|
13
|
+
export const WETH = Token.fromString('0x6a023ccd1ff6f2045c3309768ead9e68f978f6e1', CHAIN_ID, 18, 'WETH')
|
|
14
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Token } from '../tokens'
|
|
2
|
+
import { ChainId } from '../types'
|
|
3
|
+
|
|
4
|
+
export namespace Optimism {
|
|
5
|
+
export const CHAIN_ID = ChainId.OPTIMISM
|
|
6
|
+
export const ETH = Token.native(CHAIN_ID)
|
|
7
|
+
export const USDC = Token.fromString('0x0b2c639c533813f4aa9d7837caf62653d097ff85', CHAIN_ID, 6, 'USDC')
|
|
8
|
+
export const USDT = Token.fromString('0x94b008aa00579c1307b0ef2c499ad98a8ce58e58', CHAIN_ID, 6, 'USDT')
|
|
9
|
+
export const DAI = Token.fromString('0xda10009cbd5d07dd0cecc66161fc93d7c9000da1', CHAIN_ID, 18, 'DAI')
|
|
10
|
+
export const WBTC = Token.fromString('0x68f180fcce6836688e9084f035309e29bf0a2095', CHAIN_ID, 8, 'WBTC')
|
|
11
|
+
export const WETH = Token.fromString('0x4200000000000000000000000000000000000006', CHAIN_ID, 18, 'WETH')
|
|
12
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Address, ChainId } from '../types'
|
|
2
|
+
|
|
3
|
+
@json
|
|
4
|
+
export class SerializableSettler {
|
|
5
|
+
constructor(
|
|
6
|
+
public readonly address: string,
|
|
7
|
+
public readonly chainId: i32
|
|
8
|
+
) {}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class Settler {
|
|
12
|
+
constructor(
|
|
13
|
+
public readonly address: Address,
|
|
14
|
+
public readonly chainId: ChainId
|
|
15
|
+
) {}
|
|
16
|
+
|
|
17
|
+
static fromSerializable(serializable: SerializableSettler): Settler {
|
|
18
|
+
return new Settler(Address.fromString(serializable.address), serializable.chainId)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@json
|
|
23
|
+
export class SerializableContext {
|
|
24
|
+
constructor(
|
|
25
|
+
public readonly timestamp: u64,
|
|
26
|
+
public readonly consensusThreshold: u8,
|
|
27
|
+
public user: string,
|
|
28
|
+
public settlers: SerializableSettler[],
|
|
29
|
+
public configSig: string
|
|
30
|
+
) {}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class Context {
|
|
34
|
+
constructor(
|
|
35
|
+
public readonly timestamp: u64,
|
|
36
|
+
public readonly consensusThreshold: u8,
|
|
37
|
+
public user: Address,
|
|
38
|
+
public settlers: Settler[],
|
|
39
|
+
public configSig: string
|
|
40
|
+
) {}
|
|
41
|
+
|
|
42
|
+
static fromSerializable(serializable: SerializableContext): Context {
|
|
43
|
+
return new Context(
|
|
44
|
+
serializable.timestamp,
|
|
45
|
+
serializable.consensusThreshold,
|
|
46
|
+
Address.fromString(serializable.user),
|
|
47
|
+
serializable.settlers.map<Settler>((s) => Settler.fromSerializable(s)),
|
|
48
|
+
serializable.configSig
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
findSettler(chainId: ChainId): Address {
|
|
53
|
+
for (let i = 0; i < this.settlers.length; i++) {
|
|
54
|
+
if (this.settlers[i].chainId === chainId) return this.settlers[i].address
|
|
55
|
+
}
|
|
56
|
+
throw new Error(`Settler not found for chainId: ${chainId}`)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Context'
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { ListType } from './helpers'
|
|
2
|
+
import { Token, TokenAmount, USD } from './tokens'
|
|
3
|
+
import { Address, BigInt, ChainId } from './types'
|
|
4
|
+
import { Swap, Transfer, Call } from './intents'
|
|
5
|
+
import { Call as CallQuery, GetPrice, GetRelevantTokens, GetRelevantTokensResponse } from './queries'
|
|
6
|
+
import { JSON } from 'json-as/assembly'
|
|
7
|
+
import { Context, SerializableContext } from './context'
|
|
8
|
+
|
|
9
|
+
export namespace environment {
|
|
10
|
+
@external('environment', '_call')
|
|
11
|
+
declare function _call(params: string): void
|
|
12
|
+
|
|
13
|
+
@external('environment', '_swap')
|
|
14
|
+
declare function _swap(params: string): void
|
|
15
|
+
|
|
16
|
+
@external('environment', '_transfer')
|
|
17
|
+
declare function _transfer(params: string): void
|
|
18
|
+
|
|
19
|
+
@external('environment', '_getPrice')
|
|
20
|
+
declare function _getPrice(params: string): string
|
|
21
|
+
|
|
22
|
+
@external('environment', '_getRelevantTokens')
|
|
23
|
+
declare function _getRelevantTokens(params: string): string
|
|
24
|
+
|
|
25
|
+
@external('environment', '_contractCall')
|
|
26
|
+
declare function _contractCall(params: string): string
|
|
27
|
+
|
|
28
|
+
@external('environment', '_getContext')
|
|
29
|
+
declare function _getContext(): string
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Generates a Call intent containing contract calls on the blockchain.
|
|
33
|
+
* @param call - The Call intent to generate
|
|
34
|
+
*/
|
|
35
|
+
export function call(call: Call): void {
|
|
36
|
+
_call(JSON.stringify(call))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Generates a Swap intent for token exchange operations.
|
|
41
|
+
* @param swap - The Swap intent to generate
|
|
42
|
+
*/
|
|
43
|
+
export function swap(swap: Swap): void {
|
|
44
|
+
_swap(JSON.stringify(swap))
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Generates a Transfer intent for sending tokens to recipients.
|
|
49
|
+
* @param transfer - The Transfer intent to generate
|
|
50
|
+
*/
|
|
51
|
+
export function transfer(transfer: Transfer): void {
|
|
52
|
+
_transfer(JSON.stringify(transfer))
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Tells the price of a token in USD at a specific timestamp.
|
|
57
|
+
* @param token - The token to get the price of
|
|
58
|
+
* @param timestamp - The timestamp for price lookup (optional, defaults to current time)
|
|
59
|
+
* @returns The token price in USD
|
|
60
|
+
*/
|
|
61
|
+
export function getPrice(token: Token, timestamp: Date | null = null): USD {
|
|
62
|
+
const price = _getPrice(JSON.stringify(GetPrice.fromToken(token, timestamp)))
|
|
63
|
+
return USD.fromBigInt(BigInt.fromString(price))
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Tells the balances of an address for the specified tokens and chains.
|
|
68
|
+
* @param address - The address to query balances for
|
|
69
|
+
* @param chainIds - Array of chain ids to search
|
|
70
|
+
* @param usdMinAmount - Minimum USD value threshold for tokens (optional, defaults to zero)
|
|
71
|
+
* @param tokensList - List of tokens to include/exclude (optional, defaults to empty array)
|
|
72
|
+
* @param listType - Whether to include (AllowList) or exclude (DenyList) the tokens in `tokensList` (optional, defaults to DenyList)
|
|
73
|
+
* @returns Array of TokenAmount objects representing the relevant tokens
|
|
74
|
+
*/
|
|
75
|
+
export function getRelevantTokens(
|
|
76
|
+
address: Address,
|
|
77
|
+
chainIds: ChainId[],
|
|
78
|
+
usdMinAmount: USD = USD.zero(),
|
|
79
|
+
tokensList: Token[] = [],
|
|
80
|
+
listType: ListType = ListType.DenyList,
|
|
81
|
+
timestamp: Date | null = null
|
|
82
|
+
): TokenAmount[] {
|
|
83
|
+
const responseStr = _getRelevantTokens(JSON.stringify(GetRelevantTokens.init(address, chainIds, usdMinAmount, tokensList, listType, timestamp)))
|
|
84
|
+
const response = JSON.parse<GetRelevantTokensResponse[]>(responseStr)
|
|
85
|
+
return response.map<TokenAmount>((r) => r.toTokenAmount())
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Generates a contract call of a read function on the blockchain and returns the result.
|
|
90
|
+
* @param to - The contract address to call
|
|
91
|
+
* @param chainId - The blockchain network identifier
|
|
92
|
+
* @param timestamp - The timestamp for the call context (optional)
|
|
93
|
+
* @param data - The encoded function call data
|
|
94
|
+
* @returns The raw response from the contract call
|
|
95
|
+
*/
|
|
96
|
+
export function contractCall(
|
|
97
|
+
to: Address,
|
|
98
|
+
chainId: ChainId,
|
|
99
|
+
timestamp: Date | null,
|
|
100
|
+
data: string
|
|
101
|
+
): string {
|
|
102
|
+
return _contractCall(
|
|
103
|
+
JSON.stringify(CallQuery.from(to, chainId, timestamp, data))
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Tells the current execution context containing environment information.
|
|
109
|
+
* @returns The Context object containing: user, settler, timestamp, and config ID
|
|
110
|
+
*/
|
|
111
|
+
export function getContext(): Context {
|
|
112
|
+
const context = JSON.parse<SerializableContext>(_getContext())
|
|
113
|
+
return Context.fromSerializable(context)
|
|
114
|
+
}
|
|
115
|
+
}
|
package/src/evm.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { EvmDecodeParam, EvmEncodeParam } from './types'
|
|
2
|
+
import { JSON } from 'json-as/assembly'
|
|
3
|
+
|
|
4
|
+
export namespace evm {
|
|
5
|
+
@external('evm', '_encode')
|
|
6
|
+
declare function _encode(params: string): string
|
|
7
|
+
|
|
8
|
+
@external('evm', '_decode')
|
|
9
|
+
declare function _decode(params: string): string
|
|
10
|
+
|
|
11
|
+
@external('evm', '_keccak')
|
|
12
|
+
declare function _keccak(params: string): string
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Encodes parameters for EVM smart contract function calls using ABI encoding.
|
|
16
|
+
* @param callParameters - Array of parameters to encode for the contract call
|
|
17
|
+
* @returns The ABI-encoded data as a hex string
|
|
18
|
+
*/
|
|
19
|
+
export function encode(callParameters: EvmEncodeParam[]): string {
|
|
20
|
+
return _encode(JSON.stringify(callParameters))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Decodes EVM contract call response data according to specified types.
|
|
25
|
+
* @param encodedData - The encoded data configuration specifying how to decode the response
|
|
26
|
+
* @returns The decoded data as a formatted string
|
|
27
|
+
*/
|
|
28
|
+
export function decode(encodedData: EvmDecodeParam): string {
|
|
29
|
+
return _decode(JSON.stringify(encodedData))
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Computes the Keccak-256 hash of the input data.
|
|
34
|
+
* @param data - The input data to hash
|
|
35
|
+
* @returns The Keccak-256 hash as a hex string
|
|
36
|
+
*/
|
|
37
|
+
export function keccak(data: string): string {
|
|
38
|
+
return _keccak(data)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface Stringable {
|
|
2
|
+
toString(): string
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export interface Serializable {
|
|
6
|
+
serialize(): string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function serialize<T extends Stringable>(elem: T): string {
|
|
10
|
+
// eslint-disable-next-line
|
|
11
|
+
// @ts-ignore
|
|
12
|
+
if (elem instanceof Serializable) return elem.serialize()
|
|
13
|
+
return elem.toString()
|
|
14
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
export function bytesToString(bytes: Uint8Array): string {
|
|
2
|
+
return String.UTF8.decodeUnsafe(bytes.dataStart, bytes.length)
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function bytesToHexString(bytes: Uint8Array): string {
|
|
6
|
+
let hex = '0x'
|
|
7
|
+
for (let i = 0; i < bytes.length; i++) hex += bytes[i].toString(16).padStart(2, '0')
|
|
8
|
+
return hex
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function areAllZeros(str: string): boolean {
|
|
12
|
+
for (let i = 0; i < str.length; i++) if (str.charCodeAt(i) !== 48) return false
|
|
13
|
+
return true
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function normalizeScientificNotation(input: string): string {
|
|
17
|
+
let len = input.length
|
|
18
|
+
if (len === 0) return input
|
|
19
|
+
|
|
20
|
+
let i = 0
|
|
21
|
+
let sign = ''
|
|
22
|
+
if (input.charAt(0) === '-' || input.charAt(0) === '+') {
|
|
23
|
+
sign = input.charAt(0)
|
|
24
|
+
i++
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let intPart = ''
|
|
28
|
+
let fracPart = ''
|
|
29
|
+
let exponentStr = ''
|
|
30
|
+
let hasDot = false
|
|
31
|
+
let hasExponent = false
|
|
32
|
+
let exponentNegative = false
|
|
33
|
+
|
|
34
|
+
// Parse integer & fraction parts
|
|
35
|
+
for (; i < len; i++) {
|
|
36
|
+
const c = input.charAt(i)
|
|
37
|
+
if (c === '.') {
|
|
38
|
+
hasDot = true
|
|
39
|
+
continue
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (c === 'e' || c === 'E') {
|
|
43
|
+
hasExponent = true
|
|
44
|
+
i++
|
|
45
|
+
break
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (hasDot) {
|
|
49
|
+
fracPart += c
|
|
50
|
+
} else {
|
|
51
|
+
intPart += c
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Parse exponent if present
|
|
56
|
+
if (hasExponent) {
|
|
57
|
+
if (i < len && (input.charAt(i) === '+' || input.charAt(i) === '-')) {
|
|
58
|
+
exponentNegative = input.charAt(i) === '-'
|
|
59
|
+
i++
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
for (; i < len; i++) {
|
|
63
|
+
const char = input.charAt(i)
|
|
64
|
+
if (char < '0' || char > '9') throw new Error(`Invalid character in exponent part: ${char}`)
|
|
65
|
+
exponentStr += char
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (exponentStr.length === 0) return input
|
|
70
|
+
|
|
71
|
+
const exponent = I32.parseInt(exponentStr)
|
|
72
|
+
const fullDigits = intPart + fracPart
|
|
73
|
+
const shift = exponentNegative ? -exponent : exponent
|
|
74
|
+
const newDecimalPos = intPart.length + shift
|
|
75
|
+
|
|
76
|
+
if (newDecimalPos <= 0) {
|
|
77
|
+
const zeros = '0'.repeat(-newDecimalPos)
|
|
78
|
+
return sign + '0.' + zeros + fullDigits
|
|
79
|
+
} else if (newDecimalPos >= fullDigits.length) {
|
|
80
|
+
const zeros = '0'.repeat(newDecimalPos - fullDigits.length)
|
|
81
|
+
return sign + fullDigits + zeros
|
|
82
|
+
} else {
|
|
83
|
+
return sign + fullDigits.substring(0, newDecimalPos) + '.' + fullDigits.substring(newDecimalPos)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function isHex(str: string, strict: boolean = false): boolean {
|
|
88
|
+
const hasPrefix = str.startsWith('0x')
|
|
89
|
+
|
|
90
|
+
if (strict && !hasPrefix) return false
|
|
91
|
+
|
|
92
|
+
const value = hasPrefix ? str.slice(2) : str
|
|
93
|
+
|
|
94
|
+
for (let i = 0; i < value.length; i++) {
|
|
95
|
+
const c = value.charCodeAt(i)
|
|
96
|
+
const isDigit = c >= '0'.charCodeAt(0) && c <= '9'.charCodeAt(0)
|
|
97
|
+
const isLetter =
|
|
98
|
+
(c >= 'a'.charCodeAt(0) && c <= 'f'.charCodeAt(0)) || (c >= 'A'.charCodeAt(0) && c <= 'F'.charCodeAt(0))
|
|
99
|
+
if (!(isDigit || isLetter)) return false
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return true
|
|
103
|
+
}
|