├── .dockerignore
├── .example.env
├── .gitignore
├── Dockerfile
├── README.md
├── abi
└── prod
│ ├── AddressBook.abi
│ ├── GateKeeper.abi
│ ├── Governance.abi
│ ├── Minter.abi
│ ├── OrbitHub.abi
│ ├── Vault.abi
│ ├── addressbook
│ ├── Stacks.abi
│ ├── Ton.abi
│ └── Xrp.abi
│ ├── bridge
│ ├── Common.abi
│ ├── Stacks.abi
│ └── Xrp.abi
│ ├── multisig
│ ├── Common.abi
│ ├── Ed25519.abi
│ ├── Stacks.abi
│ └── Xrp.abi
│ └── zkevm
│ ├── PolygonRollupManager.abi
│ └── PolygonValidiumEtrog.abi
├── app.js
├── composes
├── bsc
│ └── docker-compose.yml
├── celo
│ └── docker-compose.yml
├── docker-compose.common.yml
├── epicleague
│ └── docker-compose.yml
├── eth
│ └── docker-compose.yml
├── faireth
│ └── docker-compose.yml
├── heco
│ └── docker-compose.yml
├── icon
│ └── docker-compose.yml
├── klaytn
│ └── docker-compose.yml
├── metadium
│ └── docker-compose.yml
├── orbit
│ └── docker-compose.yml
├── polygon
│ └── docker-compose.yml
├── poweth
│ └── docker-compose.yml
├── silicon
│ └── docker-compose.yml
├── stacks
│ └── docker-compose.yml
├── ton
│ └── docker-compose.yml
├── wemix
│ └── docker-compose.yml
└── xrp
│ └── docker-compose.yml
├── config
├── chain.json
├── governance.js
├── index.js
├── info.js
└── prod
│ ├── bsc.js
│ ├── celo.js
│ ├── chainIds.js
│ ├── endpoints.js
│ ├── epicleague.js
│ ├── eth.js
│ ├── heco.js
│ ├── hub.js
│ ├── icon.js
│ ├── klaytn.js
│ ├── l2.js
│ ├── matic.js
│ ├── metadium.js
│ ├── silicon.js
│ ├── system.js
│ ├── ton.js
│ ├── wemix.js
│ └── xrp.js
├── lib
├── api.js
├── bridgeutils.js
├── britto.js
├── decimal.js
├── request.js
├── rpcAggregator.js
├── txsender.js
├── txutils.js
└── utils.js
├── logger.js
├── package.json
├── pm2.yaml
├── routes
├── index.js
└── v1
│ └── gov.js
├── src
├── evm
│ ├── index.js
│ ├── logger.js
│ └── utils
│ │ └── packer.js
├── gov
│ ├── index.js
│ └── logger.js
├── hub
│ ├── index.js
│ ├── logger.js
│ └── utils
│ │ └── packer.js
├── icon
│ ├── index.js
│ ├── logger.js
│ └── utils
│ │ ├── icon.api.js
│ │ └── packer.js
├── monitor
│ └── index.js
├── stacks
│ ├── index.js
│ ├── logger.js
│ └── utils
│ │ ├── packer.js
│ │ └── stacks.bridgeutils.js
├── stacks_layer_1
│ ├── index.js
│ ├── logger.js
│ └── utils
│ │ ├── packer.js
│ │ └── stacks.bridgeutils.js
├── ton
│ ├── index.js
│ ├── logger.js
│ └── utils
│ │ ├── packer.js
│ │ └── ton.api.js
├── ton_layer_1
│ ├── index.js
│ ├── logger.js
│ └── utils
│ │ ├── packer.js
│ │ └── ton.api.js
└── xrp
│ ├── index.js
│ ├── logger.js
│ └── utils
│ ├── packer.js
│ ├── ripple.api.js
│ └── xrp.bridgeutils.js
├── wallet.js
└── yarn.lock
/.dockerignore:
--------------------------------------------------------------------------------
1 | # git
2 | **/.git
3 |
4 | # vscode
5 | **/.vscode
6 |
7 | # node
8 | **/node_modules
9 |
10 | # log
11 | **/logs
12 |
13 | # etc
14 | **/docs
15 |
--------------------------------------------------------------------------------
/.example.env:
--------------------------------------------------------------------------------
1 | VALIDATOR_PK=
2 |
3 | # EXPANDED NODE RPC ex) infura, alchemy, etc...
4 | # Type of value must be an array.
5 | # ex) ["https://mainnet.infura.io/v3/[PROJECT_ID]", "https://eth-mainnet.g.alchemy.com/v2/[PROJECT_ID]"]
6 | AVAX=[]
7 | BSC=[]
8 | CELO=[]
9 | ETH=[]
10 | FANTOM=[]
11 | HARMONY=[]
12 | HECO=[]
13 | KLAYTN=[]
14 | MATIC=[]
15 | XDAI=[]
16 |
17 | #KAS CREDENTIAL
18 | KAS_ACCESS_KEY_ID=
19 | KAS_SECRET_ACCESS_KEY=
20 |
21 | #TON
22 | TON_API_KEY=
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # IDE
2 | ## webstorm?
3 | .idea/
4 | ## vscode
5 | .vscode/
6 | ## MacOS
7 | *.DS_Store
8 |
9 | # node dependency
10 | ## installed modules
11 | node_modules/
12 |
13 | ## nvm
14 | .nvmrc
15 |
16 | # log
17 | logs/
18 | log/
19 |
20 | # dev config
21 | **/dev
22 |
23 | # docker-compose env_file
24 | **/.env
25 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:20 as builder
2 |
3 | WORKDIR /workspace
4 |
5 | #Build
6 | COPY package.json package.json
7 | COPY yarn.lock yarn.lock
8 | RUN yarn install --immutable --immutable-cache --check-cache
9 |
10 | COPY src src
11 |
12 | FROM node:20-alpine
13 |
14 | RUN npm install -g pm2
15 |
16 | COPY --from=builder workspace/node_modules node_modules
17 | RUN apk --no-cache add curl
18 |
19 | ARG ENV_FILE
20 | COPY $ENV_FILE .env
21 | COPY abi abi
22 | COPY config config
23 | COPY lib lib
24 | COPY routes routes
25 | COPY src src
26 | COPY app.js app.js
27 | COPY logger.js logger.js
28 | COPY wallet.js wallet.js
29 | COPY pm2.yaml pm2.yaml
30 |
31 | ENTRYPOINT ["pm2-runtime", "pm2.yaml"]
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ORBIT BRIDGE
2 |
3 | ## Table of Contents
4 |
5 | * [Overview](#overview)
6 | * [Requirements](#requirements)
7 | * [Installation](#installation)
8 | * [Run](#run)
9 | * [Parser APIs](#parser-apis)
10 | * [Syncer APIs](#syncer-apis)
11 |
12 |
13 |
14 | ## Overview
15 |
16 | Orbit Bridge is a service that allows people to transfer tokens from a chain to other various chains and this project allows anyone to act as a bridge in the token transfer process.
17 |
18 | **project modules**
19 |
20 | Parser : Gathers block info and filters Orbit Bridge's transactions out of it from various chains.
21 |
22 | Syncer : Saves the filtered info and provides data for the Operator to send transactions to various chains.
23 |
24 | Operator : Executes transactions to various chains.
25 |
26 | Validator : Checks if the transfer requests sent from various chains are valid.
27 |
28 |
29 |
30 |
31 | ## Requirements
32 |
33 | * Docker, [docker-compose](https://docs.docker.com/compose/install/)
34 | * Orbit chain contracts (multisig message wallets)
35 | * Vault contract or wallet of the origin chain
36 | * Minter contracts (destination chain)
37 | * Governance registered in Orbit chain
38 | * Origin / Destination / Orbit node endpoints (running your own node might be needed in addition)
39 |
40 |
41 |
42 |
43 | ## DETAILED GUIDE HERE
44 |
45 | * [FOR VALIDATOR](https://orbit-1.gitbook.io/orbit-bridge/validator-guide)
46 |
47 | ## Installation
48 |
49 | * Place your governance info in *[ VAULT_DIR ]/settings.js*
50 |
51 | ## Run
52 |
53 | * for ether vault validator
54 | ```bash
55 | cp .example.env ~/bridge-dockerize/composes/eth/.env
56 | sudo docker-compose -f ~/bridge-dockerize/eth/docker-compose.yml up --build -d
57 | ```
58 |
59 | ## Validator APIs
60 |
61 | GET|POST /
62 | > Returns the brief status of instance.
63 |
64 | GET|POST /v1/gov/confirm/:address/:transactionId
65 | > Returns the transaction hash that has been sent by validator.
66 |
67 |
68 |
--------------------------------------------------------------------------------
/abi/prod/GateKeeper.abi:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "constant": false,
4 | "inputs": [
5 | {
6 | "name": "",
7 | "type": "string"
8 | },
9 | {
10 | "name": "",
11 | "type": "string"
12 | },
13 | {
14 | "name": "",
15 | "type": "bytes"
16 | },
17 | {
18 | "name": "",
19 | "type": "bytes"
20 | },
21 | {
22 | "name": "",
23 | "type": "bytes"
24 | },
25 | {
26 | "name": "",
27 | "type": "bytes32[]"
28 | },
29 | {
30 | "name": "",
31 | "type": "uint256[]"
32 | },
33 | {
34 | "name": "",
35 | "type": "bytes32[]"
36 | }
37 | ],
38 | "name": "applyLimitation",
39 | "outputs": [],
40 | "payable": false,
41 | "stateMutability": "nonpayable",
42 | "type": "function"
43 | },
44 | {
45 | "constant": true,
46 | "inputs": [
47 | {
48 | "name": "",
49 | "type": "string"
50 | },
51 | {
52 | "name": "",
53 | "type": "string"
54 | },
55 | {
56 | "name": "",
57 | "type": "bytes"
58 | },
59 | {
60 | "name": "",
61 | "type": "bytes32[]"
62 | },
63 | {
64 | "name": "",
65 | "type": "uint256[]"
66 | }
67 | ],
68 | "name": "isApplied",
69 | "outputs": [
70 | {
71 | "name": "",
72 | "type": "bool"
73 | }
74 | ],
75 | "payable": false,
76 | "stateMutability": "view",
77 | "type": "function"
78 | }
79 | ]
80 |
--------------------------------------------------------------------------------
/abi/prod/Minter.abi:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "anonymous": false,
4 | "inputs": [
5 | {
6 | "indexed": false,
7 | "internalType": "bool",
8 | "name": "success",
9 | "type": "bool"
10 | },
11 | {
12 | "indexed": false,
13 | "internalType": "bytes",
14 | "name": "fromAddr",
15 | "type": "bytes"
16 | },
17 | {
18 | "indexed": false,
19 | "internalType": "address",
20 | "name": "tokenAddress",
21 | "type": "address"
22 | },
23 | {
24 | "indexed": false,
25 | "internalType": "bytes",
26 | "name": "data",
27 | "type": "bytes"
28 | }
29 | ],
30 | "name": "BridgeReceiverResult",
31 | "type": "event"
32 | },
33 | {
34 | "anonymous": false,
35 | "inputs": [
36 | {
37 | "indexed": false,
38 | "internalType": "string",
39 | "name": "fromChain",
40 | "type": "string"
41 | },
42 | {
43 | "indexed": false,
44 | "internalType": "bytes",
45 | "name": "fromAddr",
46 | "type": "bytes"
47 | },
48 | {
49 | "indexed": false,
50 | "internalType": "bytes",
51 | "name": "toAddr",
52 | "type": "bytes"
53 | },
54 | {
55 | "indexed": false,
56 | "internalType": "address",
57 | "name": "tokenAddress",
58 | "type": "address"
59 | },
60 | {
61 | "indexed": false,
62 | "internalType": "bytes32[]",
63 | "name": "bytes32s",
64 | "type": "bytes32[]"
65 | },
66 | {
67 | "indexed": false,
68 | "internalType": "uint256[]",
69 | "name": "uints",
70 | "type": "uint256[]"
71 | },
72 | {
73 | "indexed": false,
74 | "internalType": "bytes",
75 | "name": "data",
76 | "type": "bytes"
77 | }
78 | ],
79 | "name": "Swap",
80 | "type": "event"
81 | },
82 | {
83 | "anonymous": false,
84 | "inputs": [
85 | {
86 | "indexed": false,
87 | "internalType": "string",
88 | "name": "fromChain",
89 | "type": "string"
90 | },
91 | {
92 | "indexed": false,
93 | "internalType": "bytes",
94 | "name": "fromAddr",
95 | "type": "bytes"
96 | },
97 | {
98 | "indexed": false,
99 | "internalType": "bytes",
100 | "name": "toAddr",
101 | "type": "bytes"
102 | },
103 | {
104 | "indexed": false,
105 | "internalType": "address",
106 | "name": "tokenAddress",
107 | "type": "address"
108 | },
109 | {
110 | "indexed": false,
111 | "internalType": "bytes32[]",
112 | "name": "bytes32s",
113 | "type": "bytes32[]"
114 | },
115 | {
116 | "indexed": false,
117 | "internalType": "uint256[]",
118 | "name": "uints",
119 | "type": "uint256[]"
120 | },
121 | {
122 | "indexed": false,
123 | "internalType": "bytes",
124 | "name": "data",
125 | "type": "bytes"
126 | }
127 | ],
128 | "name": "SwapNFT",
129 | "type": "event"
130 | },
131 | {
132 | "anonymous": false,
133 | "inputs": [
134 | {
135 | "indexed": false,
136 | "internalType": "string",
137 | "name": "toChain",
138 | "type": "string"
139 | },
140 | {
141 | "indexed": false,
142 | "internalType": "address",
143 | "name": "fromAddr",
144 | "type": "address"
145 | },
146 | {
147 | "indexed": false,
148 | "internalType": "bytes",
149 | "name": "toAddr",
150 | "type": "bytes"
151 | },
152 | {
153 | "indexed": false,
154 | "internalType": "bytes",
155 | "name": "token",
156 | "type": "bytes"
157 | },
158 | {
159 | "indexed": false,
160 | "internalType": "address",
161 | "name": "tokenAddress",
162 | "type": "address"
163 | },
164 | {
165 | "indexed": false,
166 | "internalType": "uint8",
167 | "name": "decimal",
168 | "type": "uint8"
169 | },
170 | {
171 | "indexed": false,
172 | "internalType": "uint256",
173 | "name": "amount",
174 | "type": "uint256"
175 | },
176 | {
177 | "indexed": false,
178 | "internalType": "uint256",
179 | "name": "depositId",
180 | "type": "uint256"
181 | },
182 | {
183 | "indexed": false,
184 | "internalType": "bytes",
185 | "name": "data",
186 | "type": "bytes"
187 | }
188 | ],
189 | "name": "SwapRequest",
190 | "type": "event"
191 | },
192 | {
193 | "anonymous": false,
194 | "inputs": [
195 | {
196 | "indexed": false,
197 | "internalType": "string",
198 | "name": "toChain",
199 | "type": "string"
200 | },
201 | {
202 | "indexed": false,
203 | "internalType": "address",
204 | "name": "fromAddr",
205 | "type": "address"
206 | },
207 | {
208 | "indexed": false,
209 | "internalType": "bytes",
210 | "name": "toAddr",
211 | "type": "bytes"
212 | },
213 | {
214 | "indexed": false,
215 | "internalType": "bytes",
216 | "name": "token",
217 | "type": "bytes"
218 | },
219 | {
220 | "indexed": false,
221 | "internalType": "address",
222 | "name": "tokenAddress",
223 | "type": "address"
224 | },
225 | {
226 | "indexed": false,
227 | "internalType": "uint256",
228 | "name": "tokenId",
229 | "type": "uint256"
230 | },
231 | {
232 | "indexed": false,
233 | "internalType": "uint256",
234 | "name": "amount",
235 | "type": "uint256"
236 | },
237 | {
238 | "indexed": false,
239 | "internalType": "uint256",
240 | "name": "depositId",
241 | "type": "uint256"
242 | },
243 | {
244 | "indexed": false,
245 | "internalType": "bytes",
246 | "name": "data",
247 | "type": "bytes"
248 | }
249 | ],
250 | "name": "SwapRequestNFT",
251 | "type": "event"
252 | },
253 | {
254 | "inputs": [],
255 | "name": "getVersion",
256 | "outputs": [
257 | {
258 | "internalType": "string",
259 | "name": "",
260 | "type": "string"
261 | }
262 | ],
263 | "stateMutability": "pure",
264 | "type": "function"
265 | }
266 | ]
267 |
--------------------------------------------------------------------------------
/abi/prod/Vault.abi:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "anonymous": false,
4 | "inputs": [
5 | {
6 | "indexed": false,
7 | "internalType": "bool",
8 | "name": "success",
9 | "type": "bool"
10 | },
11 | {
12 | "indexed": false,
13 | "internalType": "bytes",
14 | "name": "fromAddress",
15 | "type": "bytes"
16 | },
17 | {
18 | "indexed": false,
19 | "internalType": "address",
20 | "name": "tokenAddress",
21 | "type": "address"
22 | },
23 | {
24 | "indexed": false,
25 | "internalType": "bytes",
26 | "name": "data",
27 | "type": "bytes"
28 | }
29 | ],
30 | "name": "BridgeReceiverResult",
31 | "type": "event"
32 | },
33 | {
34 | "anonymous": false,
35 | "inputs": [
36 | {
37 | "indexed": false,
38 | "internalType": "string",
39 | "name": "toChain",
40 | "type": "string"
41 | },
42 | {
43 | "indexed": false,
44 | "internalType": "address",
45 | "name": "fromAddr",
46 | "type": "address"
47 | },
48 | {
49 | "indexed": false,
50 | "internalType": "bytes",
51 | "name": "toAddr",
52 | "type": "bytes"
53 | },
54 | {
55 | "indexed": false,
56 | "internalType": "address",
57 | "name": "token",
58 | "type": "address"
59 | },
60 | {
61 | "indexed": false,
62 | "internalType": "uint8",
63 | "name": "decimal",
64 | "type": "uint8"
65 | },
66 | {
67 | "indexed": false,
68 | "internalType": "uint256",
69 | "name": "amount",
70 | "type": "uint256"
71 | },
72 | {
73 | "indexed": false,
74 | "internalType": "uint256",
75 | "name": "depositId",
76 | "type": "uint256"
77 | },
78 | {
79 | "indexed": false,
80 | "internalType": "bytes",
81 | "name": "data",
82 | "type": "bytes"
83 | }
84 | ],
85 | "name": "Deposit",
86 | "type": "event"
87 | },
88 | {
89 | "anonymous": false,
90 | "inputs": [
91 | {
92 | "indexed": false,
93 | "internalType": "string",
94 | "name": "toChain",
95 | "type": "string"
96 | },
97 | {
98 | "indexed": false,
99 | "internalType": "address",
100 | "name": "fromAddr",
101 | "type": "address"
102 | },
103 | {
104 | "indexed": false,
105 | "internalType": "bytes",
106 | "name": "toAddr",
107 | "type": "bytes"
108 | },
109 | {
110 | "indexed": false,
111 | "internalType": "address",
112 | "name": "token",
113 | "type": "address"
114 | },
115 | {
116 | "indexed": false,
117 | "internalType": "uint256",
118 | "name": "tokenId",
119 | "type": "uint256"
120 | },
121 | {
122 | "indexed": false,
123 | "internalType": "uint256",
124 | "name": "amount",
125 | "type": "uint256"
126 | },
127 | {
128 | "indexed": false,
129 | "internalType": "uint256",
130 | "name": "depositId",
131 | "type": "uint256"
132 | },
133 | {
134 | "indexed": false,
135 | "internalType": "bytes",
136 | "name": "data",
137 | "type": "bytes"
138 | }
139 | ],
140 | "name": "DepositNFT",
141 | "type": "event"
142 | },
143 | {
144 | "anonymous": false,
145 | "inputs": [
146 | {
147 | "indexed": false,
148 | "internalType": "string",
149 | "name": "fromChain",
150 | "type": "string"
151 | },
152 | {
153 | "indexed": false,
154 | "internalType": "bytes",
155 | "name": "fromAddr",
156 | "type": "bytes"
157 | },
158 | {
159 | "indexed": false,
160 | "internalType": "bytes",
161 | "name": "toAddr",
162 | "type": "bytes"
163 | },
164 | {
165 | "indexed": false,
166 | "internalType": "bytes",
167 | "name": "token",
168 | "type": "bytes"
169 | },
170 | {
171 | "indexed": false,
172 | "internalType": "bytes32[]",
173 | "name": "bytes32s",
174 | "type": "bytes32[]"
175 | },
176 | {
177 | "indexed": false,
178 | "internalType": "uint256[]",
179 | "name": "uints",
180 | "type": "uint256[]"
181 | },
182 | {
183 | "indexed": false,
184 | "internalType": "bytes",
185 | "name": "data",
186 | "type": "bytes"
187 | }
188 | ],
189 | "name": "Withdraw",
190 | "type": "event"
191 | },
192 | {
193 | "anonymous": false,
194 | "inputs": [
195 | {
196 | "indexed": false,
197 | "internalType": "string",
198 | "name": "fromChain",
199 | "type": "string"
200 | },
201 | {
202 | "indexed": false,
203 | "internalType": "bytes",
204 | "name": "fromAddr",
205 | "type": "bytes"
206 | },
207 | {
208 | "indexed": false,
209 | "internalType": "bytes",
210 | "name": "toAddr",
211 | "type": "bytes"
212 | },
213 | {
214 | "indexed": false,
215 | "internalType": "bytes",
216 | "name": "token",
217 | "type": "bytes"
218 | },
219 | {
220 | "indexed": false,
221 | "internalType": "bytes32[]",
222 | "name": "bytes32s",
223 | "type": "bytes32[]"
224 | },
225 | {
226 | "indexed": false,
227 | "internalType": "uint256[]",
228 | "name": "uints",
229 | "type": "uint256[]"
230 | },
231 | {
232 | "indexed": false,
233 | "internalType": "bytes",
234 | "name": "data",
235 | "type": "bytes"
236 | }
237 | ],
238 | "name": "WithdrawNFT",
239 | "type": "event"
240 | },
241 | {
242 | "inputs": [],
243 | "name": "getVersion",
244 | "outputs": [
245 | {
246 | "internalType": "string",
247 | "name": "",
248 | "type": "string"
249 | }
250 | ],
251 | "stateMutability": "pure",
252 | "type": "function"
253 | }
254 | ]
255 |
--------------------------------------------------------------------------------
/abi/prod/addressbook/Stacks.abi:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "constant": true,
4 | "inputs": [],
5 | "name": "validBlock",
6 | "outputs": [
7 | {
8 | "name": "",
9 | "type": "uint256"
10 | }
11 | ],
12 | "payable": false,
13 | "stateMutability": "view",
14 | "type": "function"
15 | },
16 | {
17 | "constant": true,
18 | "inputs": [],
19 | "name": "count",
20 | "outputs": [
21 | {
22 | "name": "",
23 | "type": "uint256"
24 | }
25 | ],
26 | "payable": false,
27 | "stateMutability": "view",
28 | "type": "function"
29 | },
30 | {
31 | "constant": true,
32 | "inputs": [],
33 | "name": "getValidInfo",
34 | "outputs": [
35 | {
36 | "name": "_receiver",
37 | "type": "address"
38 | },
39 | {
40 | "name": "_validBlock",
41 | "type": "uint256"
42 | }
43 | ],
44 | "payable": false,
45 | "stateMutability": "view",
46 | "type": "function"
47 | },
48 | {
49 | "constant": true,
50 | "inputs": [],
51 | "name": "getVersion",
52 | "outputs": [
53 | {
54 | "name": "",
55 | "type": "string"
56 | }
57 | ],
58 | "payable": false,
59 | "stateMutability": "view",
60 | "type": "function"
61 | },
62 | {
63 | "constant": true,
64 | "inputs": [
65 | {
66 | "name": "",
67 | "type": "bytes32"
68 | },
69 | {
70 | "name": "",
71 | "type": "bytes32"
72 | },
73 | {
74 | "name": "",
75 | "type": "bytes32"
76 | }
77 | ],
78 | "name": "tags",
79 | "outputs": [
80 | {
81 | "name": "",
82 | "type": "uint256"
83 | }
84 | ],
85 | "payable": false,
86 | "stateMutability": "view",
87 | "type": "function"
88 | },
89 | {
90 | "constant": false,
91 | "inputs": [
92 | {
93 | "name": "_receiver",
94 | "type": "address"
95 | },
96 | {
97 | "name": "_validBlock",
98 | "type": "uint256"
99 | }
100 | ],
101 | "name": "setInvalidParam",
102 | "outputs": [],
103 | "payable": false,
104 | "stateMutability": "nonpayable",
105 | "type": "function"
106 | },
107 | {
108 | "constant": true,
109 | "inputs": [],
110 | "name": "hub",
111 | "outputs": [
112 | {
113 | "name": "",
114 | "type": "address"
115 | }
116 | ],
117 | "payable": false,
118 | "stateMutability": "view",
119 | "type": "function"
120 | },
121 | {
122 | "constant": true,
123 | "inputs": [
124 | {
125 | "name": "",
126 | "type": "uint256"
127 | }
128 | ],
129 | "name": "addrs",
130 | "outputs": [
131 | {
132 | "name": "",
133 | "type": "bytes"
134 | }
135 | ],
136 | "payable": false,
137 | "stateMutability": "view",
138 | "type": "function"
139 | },
140 | {
141 | "constant": false,
142 | "inputs": [
143 | {
144 | "name": "_id",
145 | "type": "bytes32"
146 | }
147 | ],
148 | "name": "setId",
149 | "outputs": [],
150 | "payable": false,
151 | "stateMutability": "nonpayable",
152 | "type": "function"
153 | },
154 | {
155 | "constant": true,
156 | "inputs": [
157 | {
158 | "name": "",
159 | "type": "uint256"
160 | }
161 | ],
162 | "name": "chains",
163 | "outputs": [
164 | {
165 | "name": "",
166 | "type": "string"
167 | }
168 | ],
169 | "payable": false,
170 | "stateMutability": "view",
171 | "type": "function"
172 | },
173 | {
174 | "constant": true,
175 | "inputs": [],
176 | "name": "implementation",
177 | "outputs": [
178 | {
179 | "name": "",
180 | "type": "address"
181 | }
182 | ],
183 | "payable": false,
184 | "stateMutability": "view",
185 | "type": "function"
186 | },
187 | {
188 | "constant": false,
189 | "inputs": [
190 | {
191 | "name": "_nextOwner",
192 | "type": "address"
193 | }
194 | ],
195 | "name": "changeNextOwner",
196 | "outputs": [],
197 | "payable": false,
198 | "stateMutability": "nonpayable",
199 | "type": "function"
200 | },
201 | {
202 | "constant": false,
203 | "inputs": [],
204 | "name": "changeOwner",
205 | "outputs": [],
206 | "payable": false,
207 | "stateMutability": "nonpayable",
208 | "type": "function"
209 | },
210 | {
211 | "constant": true,
212 | "inputs": [
213 | {
214 | "name": "ctx",
215 | "type": "bytes"
216 | }
217 | ],
218 | "name": "generate",
219 | "outputs": [
220 | {
221 | "name": "",
222 | "type": "bytes32"
223 | }
224 | ],
225 | "payable": false,
226 | "stateMutability": "view",
227 | "type": "function"
228 | },
229 | {
230 | "constant": false,
231 | "inputs": [
232 | {
233 | "name": "toChain",
234 | "type": "string"
235 | },
236 | {
237 | "name": "toAddr",
238 | "type": "bytes"
239 | },
240 | {
241 | "name": "data",
242 | "type": "bytes"
243 | }
244 | ],
245 | "name": "relay",
246 | "outputs": [],
247 | "payable": false,
248 | "stateMutability": "nonpayable",
249 | "type": "function"
250 | },
251 | {
252 | "constant": true,
253 | "inputs": [],
254 | "name": "nextOwner",
255 | "outputs": [
256 | {
257 | "name": "",
258 | "type": "address"
259 | }
260 | ],
261 | "payable": false,
262 | "stateMutability": "view",
263 | "type": "function"
264 | },
265 | {
266 | "constant": false,
267 | "inputs": [
268 | {
269 | "name": "toChain",
270 | "type": "string"
271 | },
272 | {
273 | "name": "toAddr",
274 | "type": "bytes"
275 | },
276 | {
277 | "name": "data",
278 | "type": "bytes"
279 | },
280 | {
281 | "name": "validator",
282 | "type": "address"
283 | },
284 | {
285 | "name": "v",
286 | "type": "uint8"
287 | },
288 | {
289 | "name": "r",
290 | "type": "bytes32"
291 | },
292 | {
293 | "name": "s",
294 | "type": "bytes32"
295 | }
296 | ],
297 | "name": "set",
298 | "outputs": [],
299 | "payable": false,
300 | "stateMutability": "nonpayable",
301 | "type": "function"
302 | },
303 | {
304 | "constant": false,
305 | "inputs": [
306 | {
307 | "name": "_hub",
308 | "type": "address"
309 | }
310 | ],
311 | "name": "setHubContract",
312 | "outputs": [],
313 | "payable": false,
314 | "stateMutability": "nonpayable",
315 | "type": "function"
316 | },
317 | {
318 | "constant": true,
319 | "inputs": [],
320 | "name": "owner",
321 | "outputs": [
322 | {
323 | "name": "",
324 | "type": "address"
325 | }
326 | ],
327 | "payable": false,
328 | "stateMutability": "view",
329 | "type": "function"
330 | },
331 | {
332 | "constant": true,
333 | "inputs": [
334 | {
335 | "name": "tag",
336 | "type": "uint256"
337 | }
338 | ],
339 | "name": "get",
340 | "outputs": [
341 | {
342 | "name": "toChain",
343 | "type": "string"
344 | },
345 | {
346 | "name": "toAddr",
347 | "type": "bytes"
348 | },
349 | {
350 | "name": "data",
351 | "type": "bytes"
352 | }
353 | ],
354 | "payable": false,
355 | "stateMutability": "view",
356 | "type": "function"
357 | },
358 | {
359 | "constant": true,
360 | "inputs": [],
361 | "name": "id",
362 | "outputs": [
363 | {
364 | "name": "",
365 | "type": "bytes32"
366 | }
367 | ],
368 | "payable": false,
369 | "stateMutability": "view",
370 | "type": "function"
371 | },
372 | {
373 | "constant": true,
374 | "inputs": [
375 | {
376 | "name": "toChain",
377 | "type": "string"
378 | },
379 | {
380 | "name": "toAddr",
381 | "type": "bytes"
382 | },
383 | {
384 | "name": "data",
385 | "type": "bytes"
386 | }
387 | ],
388 | "name": "get",
389 | "outputs": [
390 | {
391 | "name": "tag",
392 | "type": "uint256"
393 | }
394 | ],
395 | "payable": false,
396 | "stateMutability": "view",
397 | "type": "function"
398 | },
399 | {
400 | "constant": false,
401 | "inputs": [
402 | {
403 | "name": "_newImp",
404 | "type": "address"
405 | }
406 | ],
407 | "name": "_setImplementation",
408 | "outputs": [],
409 | "payable": false,
410 | "stateMutability": "nonpayable",
411 | "type": "function"
412 | },
413 | {
414 | "constant": true,
415 | "inputs": [
416 | {
417 | "name": "",
418 | "type": "uint256"
419 | }
420 | ],
421 | "name": "datas",
422 | "outputs": [
423 | {
424 | "name": "",
425 | "type": "bytes"
426 | }
427 | ],
428 | "payable": false,
429 | "stateMutability": "view",
430 | "type": "function"
431 | },
432 | {
433 | "constant": false,
434 | "inputs": [
435 | {
436 | "name": "_newOwner",
437 | "type": "address"
438 | }
439 | ],
440 | "name": "transferOwnership",
441 | "outputs": [],
442 | "payable": false,
443 | "stateMutability": "nonpayable",
444 | "type": "function"
445 | },
446 | {
447 | "constant": true,
448 | "inputs": [],
449 | "name": "receiver",
450 | "outputs": [
451 | {
452 | "name": "",
453 | "type": "address"
454 | }
455 | ],
456 | "payable": false,
457 | "stateMutability": "view",
458 | "type": "function"
459 | },
460 | {
461 | "inputs": [],
462 | "payable": false,
463 | "stateMutability": "nonpayable",
464 | "type": "constructor"
465 | },
466 | {
467 | "payable": true,
468 | "stateMutability": "payable",
469 | "type": "fallback"
470 | },
471 | {
472 | "anonymous": false,
473 | "inputs": [
474 | {
475 | "indexed": false,
476 | "name": "toChain",
477 | "type": "string"
478 | },
479 | {
480 | "indexed": false,
481 | "name": "toAddr",
482 | "type": "bytes"
483 | },
484 | {
485 | "indexed": false,
486 | "name": "data",
487 | "type": "bytes"
488 | },
489 | {
490 | "indexed": false,
491 | "name": "hash",
492 | "type": "bytes32"
493 | }
494 | ],
495 | "name": "Relay",
496 | "type": "event"
497 | },
498 | {
499 | "anonymous": false,
500 | "inputs": [
501 | {
502 | "indexed": false,
503 | "name": "toChain",
504 | "type": "string"
505 | },
506 | {
507 | "indexed": false,
508 | "name": "toAddr",
509 | "type": "bytes"
510 | },
511 | {
512 | "indexed": false,
513 | "name": "data",
514 | "type": "bytes"
515 | },
516 | {
517 | "indexed": false,
518 | "name": "tag",
519 | "type": "uint256"
520 | },
521 | {
522 | "indexed": false,
523 | "name": "hash",
524 | "type": "bytes32"
525 | }
526 | ],
527 | "name": "Set",
528 | "type": "event"
529 | }
530 | ]
--------------------------------------------------------------------------------
/abi/prod/addressbook/Xrp.abi:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "constant": true,
4 | "inputs": [],
5 | "name": "count",
6 | "outputs": [
7 | {
8 | "name": "",
9 | "type": "uint256"
10 | }
11 | ],
12 | "payable": false,
13 | "stateMutability": "view",
14 | "type": "function"
15 | },
16 | {
17 | "constant": true,
18 | "inputs": [],
19 | "name": "getVersion",
20 | "outputs": [
21 | {
22 | "name": "",
23 | "type": "string"
24 | }
25 | ],
26 | "payable": false,
27 | "stateMutability": "view",
28 | "type": "function"
29 | },
30 | {
31 | "constant": true,
32 | "inputs": [
33 | {
34 | "name": "",
35 | "type": "bytes32"
36 | },
37 | {
38 | "name": "",
39 | "type": "bytes32"
40 | },
41 | {
42 | "name": "",
43 | "type": "bytes32"
44 | }
45 | ],
46 | "name": "tags",
47 | "outputs": [
48 | {
49 | "name": "",
50 | "type": "uint256"
51 | }
52 | ],
53 | "payable": false,
54 | "stateMutability": "view",
55 | "type": "function"
56 | },
57 | {
58 | "constant": true,
59 | "inputs": [],
60 | "name": "hub",
61 | "outputs": [
62 | {
63 | "name": "",
64 | "type": "address"
65 | }
66 | ],
67 | "payable": false,
68 | "stateMutability": "view",
69 | "type": "function"
70 | },
71 | {
72 | "constant": true,
73 | "inputs": [
74 | {
75 | "name": "",
76 | "type": "uint256"
77 | }
78 | ],
79 | "name": "addrs",
80 | "outputs": [
81 | {
82 | "name": "",
83 | "type": "bytes"
84 | }
85 | ],
86 | "payable": false,
87 | "stateMutability": "view",
88 | "type": "function"
89 | },
90 | {
91 | "constant": false,
92 | "inputs": [
93 | {
94 | "name": "_id",
95 | "type": "bytes32"
96 | }
97 | ],
98 | "name": "setId",
99 | "outputs": [],
100 | "payable": false,
101 | "stateMutability": "nonpayable",
102 | "type": "function"
103 | },
104 | {
105 | "constant": true,
106 | "inputs": [
107 | {
108 | "name": "",
109 | "type": "uint256"
110 | }
111 | ],
112 | "name": "chains",
113 | "outputs": [
114 | {
115 | "name": "",
116 | "type": "string"
117 | }
118 | ],
119 | "payable": false,
120 | "stateMutability": "view",
121 | "type": "function"
122 | },
123 | {
124 | "constant": true,
125 | "inputs": [],
126 | "name": "implementation",
127 | "outputs": [
128 | {
129 | "name": "",
130 | "type": "address"
131 | }
132 | ],
133 | "payable": false,
134 | "stateMutability": "view",
135 | "type": "function"
136 | },
137 | {
138 | "constant": true,
139 | "inputs": [
140 | {
141 | "name": "ctx",
142 | "type": "bytes"
143 | }
144 | ],
145 | "name": "generate",
146 | "outputs": [
147 | {
148 | "name": "",
149 | "type": "bytes32"
150 | }
151 | ],
152 | "payable": false,
153 | "stateMutability": "view",
154 | "type": "function"
155 | },
156 | {
157 | "constant": false,
158 | "inputs": [
159 | {
160 | "name": "toChain",
161 | "type": "string"
162 | },
163 | {
164 | "name": "toAddr",
165 | "type": "bytes"
166 | },
167 | {
168 | "name": "data",
169 | "type": "bytes"
170 | }
171 | ],
172 | "name": "relay",
173 | "outputs": [],
174 | "payable": false,
175 | "stateMutability": "nonpayable",
176 | "type": "function"
177 | },
178 | {
179 | "constant": false,
180 | "inputs": [
181 | {
182 | "name": "toChain",
183 | "type": "string"
184 | },
185 | {
186 | "name": "toAddr",
187 | "type": "bytes"
188 | },
189 | {
190 | "name": "data",
191 | "type": "bytes"
192 | },
193 | {
194 | "name": "validator",
195 | "type": "address"
196 | },
197 | {
198 | "name": "v",
199 | "type": "uint8"
200 | },
201 | {
202 | "name": "r",
203 | "type": "bytes32"
204 | },
205 | {
206 | "name": "s",
207 | "type": "bytes32"
208 | }
209 | ],
210 | "name": "set",
211 | "outputs": [],
212 | "payable": false,
213 | "stateMutability": "nonpayable",
214 | "type": "function"
215 | },
216 | {
217 | "constant": false,
218 | "inputs": [
219 | {
220 | "name": "_hub",
221 | "type": "address"
222 | }
223 | ],
224 | "name": "setHubContract",
225 | "outputs": [],
226 | "payable": false,
227 | "stateMutability": "nonpayable",
228 | "type": "function"
229 | },
230 | {
231 | "constant": true,
232 | "inputs": [],
233 | "name": "owner",
234 | "outputs": [
235 | {
236 | "name": "",
237 | "type": "address"
238 | }
239 | ],
240 | "payable": false,
241 | "stateMutability": "view",
242 | "type": "function"
243 | },
244 | {
245 | "constant": true,
246 | "inputs": [
247 | {
248 | "name": "tag",
249 | "type": "uint256"
250 | }
251 | ],
252 | "name": "get",
253 | "outputs": [
254 | {
255 | "name": "toChain",
256 | "type": "string"
257 | },
258 | {
259 | "name": "toAddr",
260 | "type": "bytes"
261 | },
262 | {
263 | "name": "data",
264 | "type": "bytes"
265 | }
266 | ],
267 | "payable": false,
268 | "stateMutability": "view",
269 | "type": "function"
270 | },
271 | {
272 | "constant": true,
273 | "inputs": [],
274 | "name": "id",
275 | "outputs": [
276 | {
277 | "name": "",
278 | "type": "bytes32"
279 | }
280 | ],
281 | "payable": false,
282 | "stateMutability": "view",
283 | "type": "function"
284 | },
285 | {
286 | "constant": true,
287 | "inputs": [
288 | {
289 | "name": "toChain",
290 | "type": "string"
291 | },
292 | {
293 | "name": "toAddr",
294 | "type": "bytes"
295 | },
296 | {
297 | "name": "data",
298 | "type": "bytes"
299 | }
300 | ],
301 | "name": "get",
302 | "outputs": [
303 | {
304 | "name": "tag",
305 | "type": "uint256"
306 | }
307 | ],
308 | "payable": false,
309 | "stateMutability": "view",
310 | "type": "function"
311 | },
312 | {
313 | "constant": false,
314 | "inputs": [
315 | {
316 | "name": "_newImp",
317 | "type": "address"
318 | }
319 | ],
320 | "name": "_setImplementation",
321 | "outputs": [],
322 | "payable": false,
323 | "stateMutability": "nonpayable",
324 | "type": "function"
325 | },
326 | {
327 | "constant": true,
328 | "inputs": [
329 | {
330 | "name": "",
331 | "type": "uint256"
332 | }
333 | ],
334 | "name": "datas",
335 | "outputs": [
336 | {
337 | "name": "",
338 | "type": "bytes"
339 | }
340 | ],
341 | "payable": false,
342 | "stateMutability": "view",
343 | "type": "function"
344 | },
345 | {
346 | "constant": false,
347 | "inputs": [
348 | {
349 | "name": "_owner",
350 | "type": "address"
351 | }
352 | ],
353 | "name": "transferOwnership",
354 | "outputs": [],
355 | "payable": false,
356 | "stateMutability": "nonpayable",
357 | "type": "function"
358 | },
359 | {
360 | "inputs": [],
361 | "payable": false,
362 | "stateMutability": "nonpayable",
363 | "type": "constructor"
364 | },
365 | {
366 | "payable": true,
367 | "stateMutability": "payable",
368 | "type": "fallback"
369 | },
370 | {
371 | "anonymous": false,
372 | "inputs": [
373 | {
374 | "indexed": false,
375 | "name": "toChain",
376 | "type": "string"
377 | },
378 | {
379 | "indexed": false,
380 | "name": "toAddr",
381 | "type": "bytes"
382 | },
383 | {
384 | "indexed": false,
385 | "name": "data",
386 | "type": "bytes"
387 | },
388 | {
389 | "indexed": false,
390 | "name": "hash",
391 | "type": "bytes32"
392 | }
393 | ],
394 | "name": "Relay",
395 | "type": "event"
396 | },
397 | {
398 | "anonymous": false,
399 | "inputs": [
400 | {
401 | "indexed": false,
402 | "name": "toChain",
403 | "type": "string"
404 | },
405 | {
406 | "indexed": false,
407 | "name": "toAddr",
408 | "type": "bytes"
409 | },
410 | {
411 | "indexed": false,
412 | "name": "data",
413 | "type": "bytes"
414 | },
415 | {
416 | "indexed": false,
417 | "name": "tag",
418 | "type": "uint256"
419 | },
420 | {
421 | "indexed": false,
422 | "name": "hash",
423 | "type": "bytes32"
424 | }
425 | ],
426 | "name": "Set",
427 | "type": "event"
428 | }
429 | ]
--------------------------------------------------------------------------------
/abi/prod/bridge/Common.abi:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "constant": true,
4 | "inputs": [],
5 | "name": "getVersion",
6 | "outputs": [
7 | {
8 | "name": "",
9 | "type": "string"
10 | }
11 | ],
12 | "payable": false,
13 | "stateMutability": "pure",
14 | "type": "function"
15 | },
16 | {
17 | "constant": true,
18 | "inputs": [],
19 | "name": "relaySwap",
20 | "outputs": [],
21 | "payable": false,
22 | "stateMutability": "view",
23 | "type": "function"
24 | },
25 | {
26 | "constant": false,
27 | "inputs": [
28 | {
29 | "name": "govId",
30 | "type": "bytes32"
31 | }
32 | ],
33 | "name": "removeBridgeInfo",
34 | "outputs": [],
35 | "payable": false,
36 | "stateMutability": "nonpayable",
37 | "type": "function"
38 | },
39 | {
40 | "constant": true,
41 | "inputs": [
42 | {
43 | "name": "govId",
44 | "type": "bytes32"
45 | }
46 | ],
47 | "name": "getGovInfo",
48 | "outputs": [
49 | {
50 | "name": "uints",
51 | "type": "uint256[]"
52 | },
53 | {
54 | "name": "bytes32s",
55 | "type": "bytes32[]"
56 | },
57 | {
58 | "name": "comment",
59 | "type": "bytes"
60 | }
61 | ],
62 | "payable": false,
63 | "stateMutability": "view",
64 | "type": "function"
65 | },
66 | {
67 | "constant": false,
68 | "inputs": [
69 | {
70 | "name": "sigs",
71 | "type": "bytes32[]"
72 | }
73 | ],
74 | "name": "validateSwap",
75 | "outputs": [
76 | {
77 | "name": "major",
78 | "type": "bool"
79 | },
80 | {
81 | "name": "vaList",
82 | "type": "address[]"
83 | }
84 | ],
85 | "payable": false,
86 | "stateMutability": "nonpayable",
87 | "type": "function"
88 | },
89 | {
90 | "constant": true,
91 | "inputs": [],
92 | "name": "implementation",
93 | "outputs": [
94 | {
95 | "name": "",
96 | "type": "address"
97 | }
98 | ],
99 | "payable": false,
100 | "stateMutability": "view",
101 | "type": "function"
102 | },
103 | {
104 | "constant": true,
105 | "inputs": [
106 | {
107 | "name": "",
108 | "type": "bytes32"
109 | },
110 | {
111 | "name": "",
112 | "type": "uint256"
113 | }
114 | ],
115 | "name": "swapData",
116 | "outputs": [
117 | {
118 | "name": "fromChain",
119 | "type": "string"
120 | },
121 | {
122 | "name": "toChain",
123 | "type": "string"
124 | },
125 | {
126 | "name": "fromAddr",
127 | "type": "bytes"
128 | },
129 | {
130 | "name": "toAddr",
131 | "type": "bytes"
132 | },
133 | {
134 | "name": "token",
135 | "type": "bytes"
136 | }
137 | ],
138 | "payable": false,
139 | "stateMutability": "view",
140 | "type": "function"
141 | },
142 | {
143 | "constant": true,
144 | "inputs": [
145 | {
146 | "name": "",
147 | "type": "bytes32"
148 | }
149 | ],
150 | "name": "isConfirmed",
151 | "outputs": [
152 | {
153 | "name": "",
154 | "type": "bool"
155 | }
156 | ],
157 | "payable": false,
158 | "stateMutability": "view",
159 | "type": "function"
160 | },
161 | {
162 | "constant": true,
163 | "inputs": [],
164 | "name": "bytes32sLength",
165 | "outputs": [
166 | {
167 | "name": "",
168 | "type": "uint256"
169 | }
170 | ],
171 | "payable": false,
172 | "stateMutability": "view",
173 | "type": "function"
174 | },
175 | {
176 | "constant": false,
177 | "inputs": [
178 | {
179 | "name": "_hubContract",
180 | "type": "address"
181 | }
182 | ],
183 | "name": "setHubContract",
184 | "outputs": [],
185 | "payable": false,
186 | "stateMutability": "nonpayable",
187 | "type": "function"
188 | },
189 | {
190 | "constant": false,
191 | "inputs": [
192 | {
193 | "name": "govId",
194 | "type": "bytes32"
195 | },
196 | {
197 | "name": "uints",
198 | "type": "uint256[]"
199 | },
200 | {
201 | "name": "bytes32s",
202 | "type": "bytes32[]"
203 | },
204 | {
205 | "name": "comment",
206 | "type": "bytes"
207 | }
208 | ],
209 | "name": "addBridgeInfo",
210 | "outputs": [],
211 | "payable": false,
212 | "stateMutability": "nonpayable",
213 | "type": "function"
214 | },
215 | {
216 | "constant": true,
217 | "inputs": [],
218 | "name": "hubContract",
219 | "outputs": [
220 | {
221 | "name": "",
222 | "type": "address"
223 | }
224 | ],
225 | "payable": false,
226 | "stateMutability": "view",
227 | "type": "function"
228 | },
229 | {
230 | "constant": true,
231 | "inputs": [
232 | {
233 | "name": "",
234 | "type": "bytes32"
235 | }
236 | ],
237 | "name": "swapCount",
238 | "outputs": [
239 | {
240 | "name": "",
241 | "type": "uint256"
242 | }
243 | ],
244 | "payable": false,
245 | "stateMutability": "view",
246 | "type": "function"
247 | },
248 | {
249 | "constant": true,
250 | "inputs": [],
251 | "name": "relaySwapNFT",
252 | "outputs": [],
253 | "payable": false,
254 | "stateMutability": "view",
255 | "type": "function"
256 | },
257 | {
258 | "constant": true,
259 | "inputs": [],
260 | "name": "uintsLength",
261 | "outputs": [
262 | {
263 | "name": "",
264 | "type": "uint256"
265 | }
266 | ],
267 | "payable": false,
268 | "stateMutability": "view",
269 | "type": "function"
270 | },
271 | {
272 | "constant": true,
273 | "inputs": [
274 | {
275 | "name": "",
276 | "type": "bytes32"
277 | }
278 | ],
279 | "name": "isValidGovId",
280 | "outputs": [
281 | {
282 | "name": "",
283 | "type": "bool"
284 | }
285 | ],
286 | "payable": false,
287 | "stateMutability": "view",
288 | "type": "function"
289 | },
290 | {
291 | "constant": true,
292 | "inputs": [
293 | {
294 | "name": "",
295 | "type": "bytes32"
296 | },
297 | {
298 | "name": "",
299 | "type": "uint256"
300 | }
301 | ],
302 | "name": "executionData",
303 | "outputs": [
304 | {
305 | "name": "",
306 | "type": "bytes"
307 | }
308 | ],
309 | "payable": false,
310 | "stateMutability": "view",
311 | "type": "function"
312 | },
313 | {
314 | "constant": false,
315 | "inputs": [
316 | {
317 | "name": "_newImp",
318 | "type": "address"
319 | }
320 | ],
321 | "name": "_setImplementation",
322 | "outputs": [],
323 | "payable": false,
324 | "stateMutability": "nonpayable",
325 | "type": "function"
326 | },
327 | {
328 | "constant": true,
329 | "inputs": [
330 | {
331 | "name": "",
332 | "type": "bytes32"
333 | }
334 | ],
335 | "name": "govInfo",
336 | "outputs": [
337 | {
338 | "name": "comment",
339 | "type": "bytes"
340 | }
341 | ],
342 | "payable": false,
343 | "stateMutability": "view",
344 | "type": "function"
345 | },
346 | {
347 | "constant": true,
348 | "inputs": [],
349 | "name": "chain",
350 | "outputs": [
351 | {
352 | "name": "",
353 | "type": "string"
354 | }
355 | ],
356 | "payable": false,
357 | "stateMutability": "view",
358 | "type": "function"
359 | },
360 | {
361 | "constant": true,
362 | "inputs": [
363 | {
364 | "name": "govId",
365 | "type": "bytes32"
366 | },
367 | {
368 | "name": "dataIndex",
369 | "type": "uint256"
370 | }
371 | ],
372 | "name": "getSwapDataArray",
373 | "outputs": [
374 | {
375 | "name": "bytes32s",
376 | "type": "bytes32[]"
377 | },
378 | {
379 | "name": "uints",
380 | "type": "uint256[]"
381 | },
382 | {
383 | "name": "vaList",
384 | "type": "address[]"
385 | }
386 | ],
387 | "payable": false,
388 | "stateMutability": "view",
389 | "type": "function"
390 | },
391 | {
392 | "constant": false,
393 | "inputs": [
394 | {
395 | "name": "sigs",
396 | "type": "bytes32[]"
397 | }
398 | ],
399 | "name": "validateSwapNFT",
400 | "outputs": [
401 | {
402 | "name": "major",
403 | "type": "bool"
404 | },
405 | {
406 | "name": "vaList",
407 | "type": "address[]"
408 | }
409 | ],
410 | "payable": false,
411 | "stateMutability": "nonpayable",
412 | "type": "function"
413 | },
414 | {
415 | "inputs": [],
416 | "payable": false,
417 | "stateMutability": "nonpayable",
418 | "type": "constructor"
419 | },
420 | {
421 | "payable": false,
422 | "stateMutability": "nonpayable",
423 | "type": "fallback"
424 | }
425 | ]
426 |
--------------------------------------------------------------------------------
/abi/prod/zkevm/PolygonValidiumEtrog.abi:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "anonymous": false,
4 | "inputs": [
5 | {
6 | "indexed": true,
7 | "internalType": "uint64",
8 | "name": "numBatch",
9 | "type": "uint64"
10 | },
11 | {
12 | "indexed": false,
13 | "internalType": "bytes32",
14 | "name": "l1InfoRoot",
15 | "type": "bytes32"
16 | }
17 | ],
18 | "name": "SequenceBatches",
19 | "type": "event"
20 | },
21 | {
22 | "inputs": [
23 | {
24 | "components": [
25 | {
26 | "internalType": "bytes32",
27 | "name": "transactionsHash",
28 | "type": "bytes32"
29 | },
30 | {
31 | "internalType": "bytes32",
32 | "name": "forcedGlobalExitRoot",
33 | "type": "bytes32"
34 | },
35 | {
36 | "internalType": "uint64",
37 | "name": "forcedTimestamp",
38 | "type": "uint64"
39 | },
40 | {
41 | "internalType": "bytes32",
42 | "name": "forcedBlockHashL1",
43 | "type": "bytes32"
44 | }
45 | ],
46 | "internalType": "struct PolygonValidiumEtrog.ValidiumBatchData[]",
47 | "name": "batches",
48 | "type": "tuple[]"
49 | },
50 | {
51 | "internalType": "uint32",
52 | "name": "l1InfoTreeLeafCount",
53 | "type": "uint32"
54 | },
55 | {
56 | "internalType": "uint64",
57 | "name": "maxSequenceTimestamp",
58 | "type": "uint64"
59 | },
60 | {
61 | "internalType": "bytes32",
62 | "name": "expectedFinalAccInputHash",
63 | "type": "bytes32"
64 | },
65 | {
66 | "internalType": "address",
67 | "name": "l2Coinbase",
68 | "type": "address"
69 | },
70 | {
71 | "internalType": "bytes",
72 | "name": "dataAvailabilityMessage",
73 | "type": "bytes"
74 | }
75 | ],
76 | "name": "sequenceBatchesValidium",
77 | "outputs": [],
78 | "stateMutability": "nonpayable",
79 | "type": "function"
80 | }
81 | ]
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | require("dotenv").config();
3 |
4 | global.ROOT = __dirname;
5 | global.logger = require('./logger');
6 | global.VERSION = process.env.VERSION;
7 |
8 | console.log(`[DEPLOYED VERSION] ${process.env.VERSION}`);
9 |
10 | const config = require(ROOT + '/config');
11 | const walletUtils = require('./wallet');
12 |
13 | const Monitor = require('./src/monitor');
14 | global.monitor = new Monitor();
15 |
16 | const settings = config.settings;
17 |
18 |
19 | let PK = process.env.VALIDATOR_PK;
20 | if(PK) {
21 | PK = Buffer.from(PK.replace("0x",""), 'hex');
22 | } else {
23 | throw `VALIDATOR_PK is undefined in .env`;
24 | }
25 |
26 | let v3 = walletUtils.getWalletFromPK(PK);
27 | if (!v3)
28 | throw 'Invalid wallet information.';
29 |
30 | let account = {
31 | address: v3.address,
32 | pk: v3.pk,
33 | publicKey: v3.publicKey,
34 | name: "validatorDocker"
35 | };
36 | global.monitor.validatorAddress = account.address;
37 | global.monitor.publicKey = account.publicKey;
38 | global.monitor.chain = config.governance.chain;
39 |
40 | logger.info(`Start Orbit Chain Validator ! : ${account.address}`);
41 |
42 | global.instances = {};
43 |
44 | let chainList = settings.chain_list;
45 | if(!chainList || chainList.length === 0) {
46 | console.log('No available chain.');
47 | process.exit(1);
48 | }
49 |
50 | chainList.forEach(key => {
51 | key = key.replace(/-v[1-9]$/, '').toLowerCase();
52 | let chain = config.chain[key] || { src: "src/evm" };
53 |
54 | console.log(`[VALIDATOR_CHAIN] key: ${key}, chain: ${JSON.stringify(chain)}`);
55 |
56 | let instance = require(ROOT + '/' + chain.src);
57 | instance = new instance(key, account);
58 |
59 | instances[key] = instance;
60 | });
61 |
62 | const gov = require(`${ROOT}/src/gov`);
63 | instances["gov"] = new gov();
64 |
65 | const express = require('express');
66 | const app = express();
67 | const PORT = process.env.PORT || 8984;
68 |
69 | const indexRouter = require("./routes/index");
70 | app.use('/', indexRouter);
71 | app.use("/v1/gov", require("./routes/v1/gov").setGovInstance(instances["gov"]));
72 |
73 | app.listen(PORT, () => {
74 | logger.info('Listening on port ' + PORT);
75 | });
76 |
--------------------------------------------------------------------------------
/composes/bsc/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | validator:
4 | extends:
5 | file: ../docker-compose.common.yml
6 | service: app
7 | ports:
8 | - 18985:8984
9 | networks:
10 | - br-bscvalidator
11 | build:
12 | args:
13 | ENV_FILE: composes/bsc/.env
14 | environment:
15 | PROFILE: prod
16 | CHAIN: bsc
17 |
18 | networks:
19 | br-bscvalidator:
20 | driver: bridge
21 | ipam:
22 | driver: default
23 | config:
24 | - subnet: 172.24.131.0/24
--------------------------------------------------------------------------------
/composes/celo/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | validator:
4 | extends:
5 | file: ../docker-compose.common.yml
6 | service: app
7 | ports:
8 | - 17060:8984
9 | networks:
10 | - br-celovalidator
11 | build:
12 | args:
13 | ENV_FILE: composes/celo/.env
14 | environment:
15 | PROFILE: prod
16 | CHAIN: celo
17 |
18 | networks:
19 | br-celovalidator:
20 | driver: bridge
21 | ipam:
22 | driver: default
23 | config:
24 | - subnet: 172.24.135.0/24
--------------------------------------------------------------------------------
/composes/docker-compose.common.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | app:
4 | build:
5 | context: ../
6 | dockerfile: ./Dockerfile
7 | environment:
8 | VERSION: v2.2.9
9 |
--------------------------------------------------------------------------------
/composes/epicleague/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | validator:
4 | extends:
5 | file: ../docker-compose.common.yml
6 | service: app
7 | ports:
8 | - 18983:8984
9 | networks:
10 | - br-epicleague
11 | build:
12 | args:
13 | ENV_FILE: composes/epicleague/.env
14 | environment:
15 | PROFILE: prod
16 | CHAIN: epicleague
17 | networks:
18 | br-epicleague:
19 | driver: bridge
20 | ipam:
21 | driver: default
22 | config:
23 | - subnet: 172.24.143.0/24
24 |
--------------------------------------------------------------------------------
/composes/eth/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | validator:
4 | extends:
5 | file: ../docker-compose.common.yml
6 | service: app
7 | ports:
8 | - 18987:8984
9 | networks:
10 | - br-ethvalidator
11 | build:
12 | args:
13 | ENV_FILE: composes/eth/.env
14 | environment:
15 | PROFILE: prod
16 | CHAIN: eth
17 | networks:
18 | br-ethvalidator:
19 | driver: bridge
20 | ipam:
21 | driver: default
22 | config:
23 | - subnet: 172.24.127.0/24
24 |
--------------------------------------------------------------------------------
/composes/faireth/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | validator:
4 | extends:
5 | file: ../docker-compose.common.yml
6 | service: app
7 | ports:
8 | - 18989:8984
9 | networks:
10 | - br-ethvalidator
11 | build:
12 | args:
13 | ENV_FILE: composes/faireth/.env
14 | environment:
15 | PROFILE: prod
16 | CHAIN: faireth
17 | networks:
18 | br-ethvalidator:
19 | driver: bridge
20 | ipam:
21 | driver: default
22 | config:
23 | - subnet: 172.24.132.0/24
24 |
--------------------------------------------------------------------------------
/composes/heco/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | validator:
4 | extends:
5 | file: ../docker-compose.common.yml
6 | service: app
7 | ports:
8 | - 17110:8984
9 | networks:
10 | - br-hecovalidator
11 | build:
12 | args:
13 | ENV_FILE: composes/heco/.env
14 | environment:
15 | PROFILE: prod
16 | CHAIN: heco
17 |
18 | networks:
19 | br-hecovalidator:
20 | driver: bridge
21 | ipam:
22 | driver: default
23 | config:
24 | - subnet: 172.24.139.0/24
--------------------------------------------------------------------------------
/composes/icon/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | validator:
4 | extends:
5 | file: ../docker-compose.common.yml
6 | service: app
7 | ports:
8 | - 18991:8984
9 | networks:
10 | - br-iconvalidator
11 | build:
12 | args:
13 | ENV_FILE: composes/icon/.env
14 | environment:
15 | PROFILE: prod
16 | CHAIN: icon
17 |
18 | networks:
19 | br-iconvalidator:
20 | driver: bridge
21 | ipam:
22 | driver: default
23 | config:
24 | - subnet: 172.24.133.0/24
25 |
--------------------------------------------------------------------------------
/composes/klaytn/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | validator:
4 | extends:
5 | file: ../docker-compose.common.yml
6 | service: app
7 | ports:
8 | - 17130:8984
9 | networks:
10 | - br-klaytnvalidator
11 | build:
12 | args:
13 | ENV_FILE: composes/klaytn/.env
14 | environment:
15 | PROFILE: prod
16 | CHAIN: klaytn
17 |
18 | networks:
19 | br-klaytnvalidator:
20 | driver: bridge
21 | ipam:
22 | driver: default
23 | config:
24 | - subnet: 172.24.141.0/24
--------------------------------------------------------------------------------
/composes/metadium/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | validator:
4 | extends:
5 | file: ../docker-compose.common.yml
6 | service: app
7 | ports:
8 | - 17197:8984
9 | networks:
10 | - br-metadiumvalidator
11 | build:
12 | args:
13 | ENV_FILE: composes/metadium/.env
14 | environment:
15 | PROFILE: prod
16 | CHAIN: metadium
17 |
18 | networks:
19 | br-metadiumvalidator:
20 | driver: bridge
21 | ipam:
22 | driver: default
23 | config:
24 | - subnet: 172.24.153.0/24
25 |
--------------------------------------------------------------------------------
/composes/orbit/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | validator:
4 | extends:
5 | file: ../docker-compose.common.yml
6 | service: app
7 | ports:
8 | - 17090:8984
9 | networks:
10 | - br-orbitvalidator
11 | build:
12 | args:
13 | ENV_FILE: composes/orbit/.env
14 | environment:
15 | PROFILE: prod
16 | CHAIN: orbit
17 |
18 | networks:
19 | br-orbitvalidator:
20 | driver: bridge
21 | ipam:
22 | driver: default
23 | config:
24 | - subnet: 172.24.155.0/24
--------------------------------------------------------------------------------
/composes/polygon/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | validator:
4 | extends:
5 | file: ../docker-compose.common.yml
6 | service: app
7 | ports:
8 | - 17152:8984
9 | networks:
10 | - br-polygonvalidator
11 | build:
12 | args:
13 | ENV_FILE: composes/polygon/.env
14 | environment:
15 | PROFILE: prod
16 | CHAIN: matic
17 |
18 | networks:
19 | br-polygonvalidator:
20 | driver: bridge
21 | ipam:
22 | driver: default
23 | config:
24 | - subnet: 172.24.143.0/24
--------------------------------------------------------------------------------
/composes/poweth/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | validator:
4 | extends:
5 | file: ../docker-compose.common.yml
6 | service: app
7 | ports:
8 | - 18990:8984
9 | networks:
10 | - br-ethvalidator
11 | build:
12 | args:
13 | ENV_FILE: composes/poweth/.env
14 | environment:
15 | PROFILE: prod
16 | CHAIN: poweth
17 | networks:
18 | br-ethvalidator:
19 | driver: bridge
20 | ipam:
21 | driver: default
22 | config:
23 | - subnet: 172.24.130.0/24
24 |
--------------------------------------------------------------------------------
/composes/silicon/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | validator:
4 | extends:
5 | file: ../docker-compose.common.yml
6 | service: app
7 | ports:
8 | - 18992:8984
9 | networks:
10 | - br-siliconvalidator
11 | build:
12 | args:
13 | ENV_FILE: composes/silicon/.env
14 | environment:
15 | PROFILE: prod
16 | CHAIN: silicon
17 | networks:
18 | br-siliconvalidator:
19 | driver: bridge
20 | ipam:
21 | driver: default
22 | config:
23 | - subnet: 172.24.127.0/24
24 |
--------------------------------------------------------------------------------
/composes/stacks/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | validator:
4 | extends:
5 | file: ../docker-compose.common.yml
6 | service: app
7 | ports:
8 | - 17143:8984
9 | networks:
10 | - br-stacksvalidator
11 | build:
12 | args:
13 | ENV_FILE: composes/stacks/.env
14 | environment:
15 | PROFILE: prod
16 | CHAIN: stacks
17 |
18 | networks:
19 | br-stacksvalidator:
20 | driver: bridge
21 | ipam:
22 | driver: default
23 | config:
24 | - subnet: 172.24.142.0/24
--------------------------------------------------------------------------------
/composes/ton/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | validator:
4 | extends:
5 | file: ../docker-compose.common.yml
6 | service: app
7 | ports:
8 | - 17173:8984
9 | networks:
10 | - br-tonvalidator
11 | build:
12 | args:
13 | ENV_FILE: composes/ton/.env
14 | environment:
15 | PROFILE: prod
16 | CHAIN: ton
17 |
18 | networks:
19 | br-tonvalidator:
20 | driver: bridge
21 | ipam:
22 | driver: default
23 | config:
24 | - subnet: 172.24.150.0/24
--------------------------------------------------------------------------------
/composes/wemix/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | validator:
4 | extends:
5 | file: ../docker-compose.common.yml
6 | service: app
7 | ports:
8 | - 17195:8984
9 | networks:
10 | - br-wemixvalidator
11 | build:
12 | args:
13 | ENV_FILE: composes/wemix/.env
14 | environment:
15 | PROFILE: prod
16 | CHAIN: wemix
17 |
18 | networks:
19 | br-wemixvalidator:
20 | driver: bridge
21 | ipam:
22 | driver: default
23 | config:
24 | - subnet: 172.24.152.0/24
25 |
--------------------------------------------------------------------------------
/composes/xrp/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | validator:
4 | extends:
5 | file: ../docker-compose.common.yml
6 | service: app
7 | ports:
8 | - 17000:8984
9 | networks:
10 | - br-xrpvalidator
11 | build:
12 | args:
13 | ENV_FILE: composes/xrp/.env
14 | environment:
15 | PROFILE: prod
16 | CHAIN: xrp
17 |
18 | networks:
19 | br-xrpvalidator:
20 | driver: bridge
21 | ipam:
22 | driver: default
23 | config:
24 | - subnet: 172.24.129.0/24
25 |
--------------------------------------------------------------------------------
/config/chain.json:
--------------------------------------------------------------------------------
1 | {
2 | "xrp": {
3 | "src": "src/xrp"
4 | },
5 | "icon": {
6 | "src": "src/icon"
7 | },
8 | "stacks_layer_1": {
9 | "src": "src/stacks_layer_1"
10 | },
11 | "stacks": {
12 | "src": "src/stacks"
13 | },
14 | "ton_layer_1": {
15 | "src": "src/ton_layer_1"
16 | },
17 | "ton": {
18 | "src": "src/ton"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/config/governance.js:
--------------------------------------------------------------------------------
1 | const settings = require(`./${process.env.PROFILE}/${process.env.CHAIN}`);
2 |
3 | module.exports = {
4 | chain: settings.bridge_address.governance.chain,
5 | address: settings.bridge_address.governance.address,
6 | bytes: settings.bridge_address.governance.bytes,
7 | id: settings.bridge_address.governance.id,
8 | };
9 |
--------------------------------------------------------------------------------
/config/index.js:
--------------------------------------------------------------------------------
1 | exports.settings = require(`./${process.env.PROFILE}/${process.env.CHAIN}`);
2 | exports.chainIds = require(`./${process.env.PROFILE}/chainIds.js`);
3 | exports.endpoints = require(`./${process.env.PROFILE}/endpoints.js`).endpoints;
4 | exports.system = require(`./${process.env.PROFILE}/system.js`);
5 | exports.chain = require(`./chain.json`);
6 | exports.governance = require(`./governance.js`);
7 | exports.info = require(`./info.js`);
8 | exports.orbitHub = require(`./${process.env.PROFILE}/hub.js`);
9 | exports.l2 = require(`./${process.env.PROFILE}/l2.js`)
10 |
--------------------------------------------------------------------------------
/config/info.js:
--------------------------------------------------------------------------------
1 | const settings = require(`./${process.env.PROFILE}/${process.env.CHAIN}`);
2 | const { endpoints } = require(`./${process.env.PROFILE}/endpoints.js`);
3 |
4 | let obj = {};
5 | for(let chain of settings.chain_list){
6 | chain = chain.toLowerCase();
7 |
8 | let key = "";
9 | if(chain.includes("-v2")) {
10 | chain = chain.split("-")[0];
11 | key = chain;
12 | }
13 | else if(chain.includes("_layer")) key = chain.split("_")[0];
14 | else key = chain;
15 |
16 | let ENDPOINT = endpoints[key];
17 | let CONTRACT_ADDRESS = settings.bridge_address[key] || {};
18 |
19 | let CHAIN_ID = ENDPOINT.chain_id;
20 | let GAS_PRICE = ENDPOINT.gas_price;
21 |
22 | obj[chain] = { ENDPOINT, CONTRACT_ADDRESS, CHAIN_ID, GAS_PRICE };
23 |
24 | if(key === "eth") obj[chain].ETH_TERMINAL_TOTAL_DIFFICULTY = ENDPOINT.terminal_total_difficulty || "58750000000000000000000";
25 | }
26 | obj.ADDRESS_BOOK = settings.silicon
27 | module.exports = Object.assign({}, obj);
28 |
--------------------------------------------------------------------------------
/config/prod/bsc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // operating chain list
3 | chain_list: [
4 | 'klaytn',
5 | 'bsc',
6 | 'eth',
7 | 'matic',
8 | 'avax',
9 | 'ton',
10 | 'wemix',
11 | 'metadium',
12 | 'silicon',
13 | ],
14 |
15 | // Bridge Addresses
16 | bridge_address: {
17 | bsc: {
18 | vault: "0x89c527764f03BCb7dC469707B23b79C1D7Beb780",
19 | multisig: "0xf2C5a817cc8FFaAB4122f2cE27AB8486DFeAb09F",
20 | admin: "0x8D5DcEab358979101dC96A62e08296269F6BD1bd",
21 | },
22 | klaytn: {
23 | minter: "0xB0a83941058b109Bd0543fa26d22eFb8a2D0f431",
24 | multisig: "0x937936FF183102Dfb1609D5dbFbC50201f92c744",
25 | },
26 | matic: {
27 | minter: "0x89c527764f03BCb7dC469707B23b79C1D7Beb780",
28 | multisig: "0xf2C5a817cc8FFaAB4122f2cE27AB8486DFeAb09F",
29 | admin: "0x8D5DcEab358979101dC96A62e08296269F6BD1bd",
30 | },
31 | avax: {
32 | minter: "0xC91D164267De757fe7f5569868dc2a1Ca363c136",
33 | multisig: "0xD5afF4221b353Ab0A3dd6ad7C1FB97e582DC0C9c",
34 | admin: "0xe1bbfc002714bede0f9ee84e5d1cb4cf3a3a9e75"
35 | },
36 | eth: {
37 | minter: "0x166E514c465EF0DB69246e14C6bA866F91B1e061",
38 | multisig: "0x3DE5098FBdb858567542A949B1CE22C61eae14FB",
39 | admin: "0xE3b4270592E217d1122ddCAeBa22Ac415D718A39",
40 | },
41 | ton: {
42 | minter: "EQDABRjlDIBMx_BTNp-TvVjQZXjqfxq2y50jmhyZSJ58bB0R",
43 | multisig: "EQAs_E5Ta00Oo5gBoAevL4npbZLLOFZuvptpUeSdRnFK6mFG",
44 | },
45 | wemix: {
46 | minter: "0xfe4a11ec60A52A5593649510f249FEbE14Ad4e70",
47 | multisig: "0x3F4D41077dA83d6A57d8d0Cd692cd49C997bCE4F",
48 | admin: "0xcCED7af08E3E37e5C822412E0CaEE1Fb99cCB4d1"
49 | },
50 | metadium: {
51 | minter: "0x9DC1cb0a52fC34659D18B0F31e26582a8Db609b5",
52 | multisig: "0xDf4f362E6C3Baa3Fc8Fb0179498e6c80c35Cf547",
53 | admin: "0xa37581EDC6135585287675Ee6E517897E3c42D38"
54 | },
55 | silicon: {
56 | minter: "0xE82b8C388E0bcF7C01D05B2cE678f6d012c9B7D9",
57 | multisig: "0xFf46d621318Dcaf14f09cc7A50a68230f3562e11",
58 | admin: "0x406134c9B11dcc132d4cB810D283FbE6E31874De",
59 | },
60 | governance: {
61 | chain: "BSC",
62 | address: "0x89c527764f03BCb7dC469707B23b79C1D7Beb780",
63 | bytes: "0x89c527764f03BCb7dC469707B23b79C1D7Beb780",
64 | id: "0xa83e44c751c7b6296864c8145d325c9a9397f30adfc5a92c840fb7cb688775b3",
65 | },
66 | }
67 | }
--------------------------------------------------------------------------------
/config/prod/celo.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // operating chain list
3 | chain_list: [
4 | 'celo',
5 | 'klaytn',
6 | ],
7 |
8 | // Bridge Addresses
9 | bridge_address: {
10 | klaytn: {
11 | minter: "0x979cD0826C2bf62703Ef62221a4feA1f23da3777",
12 | multisig: "0xE665028E06Cab79928D8e607E0de99FfD7Eb76A7",
13 | },
14 | celo: {
15 | vault: "0x979cD0826C2bf62703Ef62221a4feA1f23da3777",
16 | multisig: "0xE665028E06Cab79928D8e607E0de99FfD7Eb76A7",
17 | admin: "0x6a1cf2e4b8DF2C2707e34cad35D8AF4535510F53",
18 | },
19 | governance: {
20 | chain: "CELO",
21 | address: "0x979cD0826C2bf62703Ef62221a4feA1f23da3777",
22 | bytes: "0x979cD0826C2bf62703Ef62221a4feA1f23da3777",
23 | id: "0x6c09d7b79b91a3d49c3648a1bbc811f1b99f16045218e72a597a7692580ccab1",
24 | },
25 | }
26 | }
--------------------------------------------------------------------------------
/config/prod/chainIds.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | AVAX: "0x774ad9b69090d3c3929d274caaa0fa109b2b15f39a24adb860787d10b3eba8c9",
3 | BSC: "0x252e9f7af69e5f718475e854c8a4ec34eb5262a68da244c610f2b501269572b6",
4 | ETH: "0xd71495681cc4f63a417797e97853f60220cdc1ba31deb555f2318ab770b3ca68",
5 | KLAYTN: "0x8e890c70aac933231508c13b4c58f6d67fad7e9f97cce65be0d4c82af40f0b84",
6 | MATIC: "0x3639710ae7ba531864771e9ceaea76d7a055ee9b377e2caabf886759d99b385b",
7 | METADIUM: "0xcede49e6cd419f5b9cbd2bb538ab0094cde0294b9c81ba79f2fe60ee3b81196e",
8 | SILICON: "0x738959fe9c00c831e32f667ad0ad87fb56305c649e3056e146eb76e4e63f27a3",
9 | WEMIX: "0x5560fdf32b99e139147611cfafb3bbf93294e3ac776977c78617aea67bcc93b3",
10 | TON_LAYER_1: "0x7fbf8c6a40d71b9a23ab3fe0cf9020cca506716634e0178a4fc087899130a6b0",
11 | TON: "0x57643076c3a92f82c3fea3dd79d4cfdfa8b938157ec73abcf2abfffb3de56f5a",
12 | }
--------------------------------------------------------------------------------
/config/prod/endpoints.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // Node Endpoints
3 | endpoints : {
4 | avax: {
5 | rpc: ["https://avalanche-c-chain-rpc.publicnode.com", "https://ava-mainnet.public.blastapi.io/ext/bc/C/rpc", "http://prd-avax-mainnet.node.ozys.work:8545/ext/bc/C/rpc"],
6 | chain_id: '0xa86a',
7 | confirm: 10
8 | },
9 | bsc: {
10 | rpc : ["https://bsc-dataseed.binance.org", "https://bsc-dataseed1.binance.org", "http://prd-bsc-mainnet-rpc.node.ozys.work:8545"],
11 | confirm: 10
12 | },
13 | celo: {
14 | rpc: ["https://forno.celo.org", "https://rpc.ankr.com/celo", "http://prd-celo-mainnet-rpc.node.ozys.work:8545"],
15 | chain_id: '0xa4ec',
16 | confirm: 10
17 | },
18 | eth: {
19 | rpc: ["http://prd-eth-mainnet-erpc.node.ozys.work:8545", "https://ethereum-rpc.publicnode.com", "https://eth.drpc.org"],
20 | beacon: "http://prd-eth-mainnet-brpc.node.ozys.work:8545",
21 | chain_id: '0x1',
22 | terminal_total_difficulty: "58750000000000000000000",
23 | confirm: 10
24 | },
25 | faireth: {
26 | rpc: "https://rpc.etherfair.org",
27 | socket: "wss://rpc.etherfair.org",
28 | chain_id: "0x7D44C",
29 | confirm: 10
30 | },
31 | fantom: {
32 | rpc: ["https://rpc.ftm.tools", "https://rpc.fantom.network", "https://rpc.ankr.com/fantom", "http://prd-fantom-mainnet-rpc.node.ozys.work:8545"],
33 | chain_id: '0xfa',
34 | confirm: 10
35 | },
36 | heco: {
37 | rpc : ["https://http-mainnet-node.huobichain.com", "http://prd-heco-mainnet-rpc.node.ozys.work:8545", "https://http-mainnet.hecochain.com"],
38 | chain_id: '0x80',
39 | confirm: 10
40 | },
41 | icon: {
42 | api: 'https://ctz.solidwallet.io/api/v3',
43 | rpc: 'https://ctz.solidwallet.io/api/v3',
44 | debug: 'https://ctz.solidwallet.io/api/debug/v3',
45 | version: 3,
46 | nid: 1,
47 | confirm: 10
48 | },
49 | klaytn: {
50 | is_kas: false,
51 | kas: {
52 | // KAS Default
53 | rpc: "https://node-api.klaytnapi.com/v1/klaytn",
54 | chain_id: 8217
55 | },
56 | rpc: ["https://public-en.node.kaia.io", "https://kaia.blockpi.network/v1/rpc/public", "https://klaytn.drpc.org"],
57 | confirm: 10
58 | },
59 | silicon: {
60 | rpc: ["https://rpc.silicon.network", "https://silicon-rpc-seed3.node.ozys.work", "https://silicon-mainnet.nodeinfra.com"],
61 | chain_id: 2355,
62 | confirm: 10
63 | },
64 | matic: {
65 | rpc : ["https://polygon-rpc.com", "https://polygon-bor-rpc.publicnode.com", "http://prd-matic-bor-mainnet-rpc.node.ozys.work:8545", "https://1rpc.io/matic"],
66 | chain_id: '0x89',
67 | confirm: 10
68 | },
69 | metadium: {
70 | rpc: ["https://api.metadium.com/prod"],
71 | socket: "ws://prd-meta-mainnet-ws.node.ozys.work:8545 ",
72 | confirm: 10
73 | },
74 | oec: {
75 | rpc: ["https://exchainrpc.okex.org", "http://prd-oktc-mainnet-rpc.node.ozys.work:8545"],
76 | chain_id: 66,
77 | confirm: 10
78 | },
79 | poweth: {
80 | rpc: "https://mainnet.ethereumpow.org",
81 | socket: "wss://mainnet.ethereumpow.org",
82 | chain_id: "0x2711",
83 | confirm: 10
84 | },
85 | stacks: {
86 | url: "https://stacks-node-api.mainnet.stacks.co",
87 | network: "mainnet",
88 | confirm: 10
89 | },
90 | ton: {
91 | rpc: "https://toncenter.com/api/v2/jsonRPC",
92 | confirm: 10
93 | },
94 | wemix: {
95 | rpc: "https://api.wemix.com",
96 | socket: "wss://ws.wemix.com",
97 | chain_id: 1111,
98 | confirm: 10
99 | },
100 | xdai: {
101 | rpc: ["https://rpc.gnosischain.com", "https://rpc.ankr.com/gnosis", "https://gnosis-mainnet.public.blastapi.io"],
102 | confirm: 10
103 | },
104 | xrp: {
105 | rpc: "https://s1.ripple.com:51234",
106 | socket: "wss://s1.ripple.com:443",
107 | confirm: 10
108 | },
109 | },
110 | VALIDATOR_MONITOR: {
111 | ozys: {
112 | monitor: "https://va.bridge.orbitchain.io/governance/report",
113 | orbit: "https://api.bridge.orbitchain.io",
114 | validator: "https://va.bridge.orbitchain.io",
115 | bible: "https://bridge.orbitchain.io/open",
116 | interval: 60 * 1000,
117 | },
118 | },
119 | }
120 |
--------------------------------------------------------------------------------
/config/prod/epicleague.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | chain_list: [
3 | "eth",
4 | "bsc",
5 | "matic",
6 | ],
7 |
8 | // Bridge Addresses
9 | bridge_address: {
10 | eth: {
11 | vault: "0x09Ac709B11E1B7d08E8bcab0472674a9d77B13eb",
12 | multisig: "0x09Ac709B11E1B7d08E8bcab0472674a9d77B13eb"
13 | },
14 | bsc: {
15 | minter: "0x09Ac709B11E1B7d08E8bcab0472674a9d77B13eb",
16 | multisig: "0xbbf04C01AAA813c61525551e4d8014A2001500E3",
17 | admin: "0xef6D4C123078409f49037a85D3ADbcc5411DeA33"
18 | },
19 | matic: {
20 | minter: "0x09Ac709B11E1B7d08E8bcab0472674a9d77B13eb",
21 | multisig: "0xbbf04C01AAA813c61525551e4d8014A2001500E3",
22 | admin: "0xef6D4C123078409f49037a85D3ADbcc5411DeA33"
23 | },
24 | governance: {
25 | chain: "ETH",
26 | address: "0x09Ac709B11E1B7d08E8bcab0472674a9d77B13eb",
27 | bytes: "0x09Ac709B11E1B7d08E8bcab0472674a9d77B13eb",
28 | id: "0xd4ff2b907575ecee91528be826b644668b6017edb704f1a4fe8abb63123b75ff"
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/config/prod/eth.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // operating chain list
3 | chain_list: [
4 | 'eth',
5 | 'klaytn',
6 | 'icon',
7 | 'avax',
8 | 'bsc',
9 | 'matic',
10 | 'ton',
11 | 'wemix'
12 | ],
13 |
14 | // Bridge Addresses
15 | bridge_address: {
16 | eth: {
17 | vault: "0x1bf68a9d1eaee7826b3593c20a0ca93293cb489a",
18 | },
19 | avax: {
20 | minter: "0x6BD8E3beEC87176BA9c705c9507Aa5e6F0E6706f",
21 | multisig: "0xFA9c34485c3a706725130E8e0217431AC000E31e",
22 | admin: "0xe62Fa6C59AD14B46d4e7791FA817030732953b79",
23 | },
24 | bsc: {
25 | minter: "0x6BD8E3beEC87176BA9c705c9507Aa5e6F0E6706f",
26 | multisig: "0xFA9c34485c3a706725130E8e0217431AC000E31e",
27 | admin: "0xe62Fa6C59AD14B46d4e7791FA817030732953b79",
28 | },
29 | icon: {
30 | minter: "cx0eb215b6303142e37c0c9123abd1377feb423f0e",
31 | multisig: "cxa032c913d5d9b7577e2b19f39d91985e5c260577",
32 | },
33 | klaytn: {
34 | minter: "0x60070F5D2e1C1001400A04F152E7ABD43410F7B9",
35 | multisig: "0x74bB62c446c592a5A8424d4f9437242df1e26BF0",
36 | },
37 | matic: {
38 | minter: "0x6BD8E3beEC87176BA9c705c9507Aa5e6F0E6706f",
39 | multisig: "0xFA9c34485c3a706725130E8e0217431AC000E31e",
40 | admin: "0xe62Fa6C59AD14B46d4e7791FA817030732953b79",
41 | },
42 | ton: {
43 | minter: "EQAihs8RdUgLANjNypV5LgaUHfdoUsMVL5o06K2F-qFSki00",
44 | multisig: "EQBbAqI1eVJ8PbZpKXA5njk6hq8Q6ZUxwXLZf-ntG1wf90Tm",
45 | },
46 | wemix: {
47 | minter: "0x6BD8E3beEC87176BA9c705c9507Aa5e6F0E6706f",
48 | multisig: "0xCeBB82777bfe09c65AA47E8dD09a2f3972467901",
49 | admin: "0xe62Fa6C59AD14B46d4e7791FA817030732953b79",
50 | },
51 | governance: {
52 | chain: "ETH",
53 | address: "0x1bf68a9d1eaee7826b3593c20a0ca93293cb489a",
54 | bytes: "0x1bf68a9d1eaee7826b3593c20a0ca93293cb489a",
55 | id: "0x50f408f4b0fb17bf4f5143de4bd95802410d00422f008e9deef06fb101a0f060",
56 | },
57 | }
58 | }
--------------------------------------------------------------------------------
/config/prod/heco.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | chain_list: [
3 | 'avax',
4 | 'bsc',
5 | 'celo',
6 | 'heco',
7 | 'fantom',
8 | 'klaytn',
9 | 'matic',
10 | 'oec',
11 | 'xdai',
12 | ],
13 |
14 | // Bridge Addresses
15 | bridge_address: {
16 | avax: {
17 | minter: "0x38C92A7C2B358e2F2b91723e5c4Fc7aa8b4d279F",
18 | multisig: "0x8B8B037CC309bf46E23226BF38BE433ABC284Cf6",
19 | admin: "0x2bA5049df54aEde8d26786DFBE0cf0fDF7eDBBAd",
20 | },
21 | bsc: {
22 | minter: "0x38C92A7C2B358e2F2b91723e5c4Fc7aa8b4d279F",
23 | multisig: "0x8B8B037CC309bf46E23226BF38BE433ABC284Cf6",
24 | admin: "0x2bA5049df54aEde8d26786DFBE0cf0fDF7eDBBAd",
25 | },
26 | celo: {
27 | minter: "0x38C92A7C2B358e2F2b91723e5c4Fc7aa8b4d279F",
28 | multisig: "0x8B8B037CC309bf46E23226BF38BE433ABC284Cf6",
29 | admin: "0x2bA5049df54aEde8d26786DFBE0cf0fDF7eDBBAd",
30 | },
31 | fantom: {
32 | minter: "0x38C92A7C2B358e2F2b91723e5c4Fc7aa8b4d279F",
33 | multisig: "0x8B8B037CC309bf46E23226BF38BE433ABC284Cf6",
34 | admin: "0x2bA5049df54aEde8d26786DFBE0cf0fDF7eDBBAd",
35 | },
36 | heco: {
37 | vault: "0x38C92A7C2B358e2F2b91723e5c4Fc7aa8b4d279F",
38 | multisig: "0x8B8B037CC309bf46E23226BF38BE433ABC284Cf6",
39 | admin: "0x2bA5049df54aEde8d26786DFBE0cf0fDF7eDBBAd",
40 | },
41 | klaytn: {
42 | minter: "0x38C92A7C2B358e2F2b91723e5c4Fc7aa8b4d279F",
43 | multisig: "0x8B8B037CC309bf46E23226BF38BE433ABC284Cf6",
44 | },
45 | matic: {
46 | minter: "0x38C92A7C2B358e2F2b91723e5c4Fc7aa8b4d279F",
47 | multisig: "0x8B8B037CC309bf46E23226BF38BE433ABC284Cf6",
48 | admin: "0x2bA5049df54aEde8d26786DFBE0cf0fDF7eDBBAd",
49 | },
50 | oec: {
51 | minter: "0x38C92A7C2B358e2F2b91723e5c4Fc7aa8b4d279F",
52 | multisig: "0x8B8B037CC309bf46E23226BF38BE433ABC284Cf6",
53 | admin: "0x2bA5049df54aEde8d26786DFBE0cf0fDF7eDBBAd",
54 | },
55 | xdai: {
56 | minter: "0x38C92A7C2B358e2F2b91723e5c4Fc7aa8b4d279F",
57 | multisig: "0x8B8B037CC309bf46E23226BF38BE433ABC284Cf6",
58 | admin: "0x2bA5049df54aEde8d26786DFBE0cf0fDF7eDBBAd",
59 | },
60 | governance: {
61 | chain: "HECO",
62 | address: "0x38C92A7C2B358e2F2b91723e5c4Fc7aa8b4d279F",
63 | bytes: "0x38C92A7C2B358e2F2b91723e5c4Fc7aa8b4d279F",
64 | id: "0x1958c3d245eed5312fa97ca358876d36b45c0905dd322b73efd66c8f836fb67f",
65 | },
66 | }
67 | }
--------------------------------------------------------------------------------
/config/prod/hub.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | address: "0xb5680a55d627c52de992e3ea52a86f19da475399"
3 | }
--------------------------------------------------------------------------------
/config/prod/icon.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // operating chain list
3 | chain_list: [
4 | "icon",
5 | "klaytn",
6 | ],
7 |
8 | // Bridge Addresses
9 | bridge_address: {
10 | klaytn: {
11 | minter: "0xcD953813896F766f1Eb9B613610E1752eD6F8395",
12 | multisig: "0xF6E3F95a1AC1C9A86Fa5C3c61DbD3D3BC6B566B5",
13 | },
14 | icon: {
15 | vault: "cxa82aa03dae9ca03e3537a8a1e2f045bcae86fd3f",
16 | multisig: "cxd41e399c809a3671191c916d619e4d0fef04feea",
17 | },
18 | governance: {
19 | chain: "ICON",
20 | address: "cxa82aa03dae9ca03e3537a8a1e2f045bcae86fd3f",
21 | bytes: "0x01a82aa03dae9ca03e3537a8a1e2f045bcae86fd3f",
22 | id: "0x6432be95e9ad50213ac792ac86951833cb24e47523feb923a677c711b05539e7",
23 | },
24 | }
25 | }
--------------------------------------------------------------------------------
/config/prod/klaytn.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | chain_list: [
3 | 'avax',
4 | 'bsc',
5 | 'klaytn',
6 | 'matic',
7 | 'eth',
8 | 'ton',
9 | 'wemix',
10 | 'silicon',
11 | ],
12 |
13 | // Bridge Addresses
14 | bridge_address: {
15 | avax: {
16 | minter: "0x9abc3f6c11dbd83234d6e6b2c373dfc1893f648d",
17 | multisig: "0xcAA1B50341ad8Eb69A7bb1985bf39224044B1d48",
18 | admin: "0x3060E2fbDB75663b50bf9e629693DC39A4418736",
19 | },
20 | bsc: {
21 | minter: "0x9abc3f6c11dbd83234d6e6b2c373dfc1893f648d",
22 | multisig: "0xcAA1B50341ad8Eb69A7bb1985bf39224044B1d48",
23 | admin: "0x3060E2fbDB75663b50bf9e629693DC39A4418736",
24 | },
25 | eth: {
26 | minter: "0x012c6d79b189e1aBD1EFaC759b275c5D49Abd164",
27 | multisig: "0x9Abc3F6c11dBd83234D6E6b2c373Dfc1893F648D",
28 | admin: "0x3060E2fbDB75663b50bf9e629693DC39A4418736",
29 | },
30 | klaytn: {
31 | vault: "0x9abc3f6c11dbd83234d6e6b2c373dfc1893f648d",
32 | multisig: "0x9abc3f6c11dbd83234d6e6b2c373dfc1893f648d",
33 | },
34 | matic: {
35 | minter: "0x9abc3f6c11dbd83234d6e6b2c373dfc1893f648d",
36 | multisig: "0xcAA1B50341ad8Eb69A7bb1985bf39224044B1d48",
37 | admin: "0x3060E2fbDB75663b50bf9e629693DC39A4418736",
38 | },
39 | wemix: {
40 | minter: "0xCd3698A1392A1Dd66a4934b69CCf800964817CA1",
41 | multisig: "0x58A42330c0984babD5DEc2C943eAA345B7f41e44",
42 | admin: "0x8966c07b38dcb277f1e5264368Cafb289DBCab4f",
43 | },
44 | ton: {
45 | minter: "EQAlMRLTYOoG6kM0d3dLHqgK30ol3qIYwMNtEelktzXP_pD5",
46 | multisig: "EQAblz6Xr6b-7eLAWeagIK2Dn-g81YiNpu0okHfc9EwY9_72",
47 | },
48 | silicon: {
49 | minter: "0x53ab0acE2f5245297917687F2a0380cf82055C57",
50 | multisig: "0x0e892b6119864592e86117d17Ef49db2f7C92258",
51 | admin: "0xE0273bDF3A45BbbB2506fDBBae96871D49d5FD19",
52 | },
53 | governance: {
54 | chain: "KLAYTN",
55 | address: "0x9abc3f6c11dbd83234d6e6b2c373dfc1893f648d",
56 | bytes: "0x9abc3f6c11dbd83234d6e6b2c373dfc1893f648d",
57 | id: "0xf8e356a0087a537f3e1a481c46ed4bdc4438723ebe666d8a3e7e6f4021d740a4",
58 | },
59 | }
60 | }
--------------------------------------------------------------------------------
/config/prod/l2.js:
--------------------------------------------------------------------------------
1 | // l1 chain & contract infomation
2 | module.exports = {
3 | silicon : {
4 | l1_chain: "eth",
5 | PolygonValidiumEtrog: "0x419dcd0f72ebafd3524b65a97ac96699c7fbebdb", // sequence
6 | PolygonRollupManager: "0x5132A183E9F3CB7C848b0AAC5Ae0c4f0491B7aB2" // verify
7 | }
8 | }
--------------------------------------------------------------------------------
/config/prod/matic.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | chain_list: [
3 | 'avax',
4 | 'bsc',
5 | 'klaytn',
6 | 'matic',
7 | 'eth',
8 | "ton",
9 | "silicon",
10 | ],
11 |
12 | // Bridge Addresses
13 | bridge_address: {
14 | avax: {
15 | minter: "0x506DC4c6408813948470a06ef6e4a1DaF228dbd5",
16 | multisig: "0x98d729f9bD84AAC94639700e71B7916018A708B1",
17 | admin: "0x3b31c980598f9237d9C14bB44118773b92174720",
18 | },
19 | bsc: {
20 | minter: "0x506DC4c6408813948470a06ef6e4a1DaF228dbd5",
21 | multisig: "0x98d729f9bD84AAC94639700e71B7916018A708B1",
22 | admin: "0x3b31c980598f9237d9C14bB44118773b92174720",
23 | },
24 | eth: {
25 | minter: "0x506DC4c6408813948470a06ef6e4a1DaF228dbd5",
26 | multisig: "0x98d729f9bD84AAC94639700e71B7916018A708B1",
27 | admin: "0x3b31c980598f9237d9C14bB44118773b92174720",
28 | },
29 | klaytn: {
30 | minter: "0x506DC4c6408813948470a06ef6e4a1DaF228dbd5",
31 | multisig: "0x98d729f9bD84AAC94639700e71B7916018A708B1",
32 | },
33 | matic: {
34 | vault: "0x506DC4c6408813948470a06ef6e4a1DaF228dbd5",
35 | multisig: "0x98d729f9bD84AAC94639700e71B7916018A708B1",
36 | admin: "0x3b31c980598f9237d9C14bB44118773b92174720",
37 | },
38 | ton: {
39 | minter: "EQAZPJjpx_VCoaAJW78qYtbUK59IsheysCRgzaSUcp7k_Jqd",
40 | multisig: "EQBbdymUiXgv2FK4yGwHmXC2mvnpwxUT7U9tj-nonXXnrv0L",
41 | },
42 | silicon: {
43 | minter: "0xd4058d1f1071c03CBC19cb149885ecAda79B99b8",
44 | multisig: "0x41c687a333a9586dBdA5C1B5e8F224bF77800E87",
45 | admin: "0x72f757F0DA2ec2c3ab6a61e177e95b70ECf65E21",
46 | },
47 | governance: {
48 | chain: "MATIC",
49 | address: "0x506DC4c6408813948470a06ef6e4a1DaF228dbd5",
50 | bytes: "0x506DC4c6408813948470a06ef6e4a1DaF228dbd5",
51 | id: "0xaf9c9bf1d10f96432ef783c6ff34815d5e22e5083554a9940cf5dcbbdce7cfe7",
52 | },
53 | }
54 | }
--------------------------------------------------------------------------------
/config/prod/metadium.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | chain_list: [
3 | "avax",
4 | "bsc",
5 | "eth",
6 | "klaytn",
7 | "matic",
8 | "metadium",
9 | "ton",
10 | "wemix"
11 | ],
12 | bridge_address: {
13 | avax: {
14 | minter: "0xf4D9c96896d8dE644E229e37FdC9Cb02bee65e51",
15 | multisig: "0x218c6E663e43542d90E4Bf6247b1E9e719ce0FAF",
16 | admin: "0xA41eC45f1828bD1b3e91Ca31Bf005AfeA540D6f2"
17 | },
18 | bsc: {
19 | minter: "0x3F0ADd7b24080352E4EC7DD8b9F6B8e7BbB36717",
20 | multisig: "0x005be6cAF238609E23949EF75fC1a0a13Ea02928",
21 | admin: "0x0A1ce5a7867BA59Ce9807C0774acf8b376f52E4F"
22 | },
23 | eth: {
24 | minter: "0x06d1484298773B74235cD400926a7b1e65fdea55",
25 | multisig: "0x77258E1e42D26817Cc840a5906C212B3B8CB636a",
26 | admin: "0x77C24eB33FE159606397a5309d6C4D841e160600"
27 | },
28 | klaytn: {
29 | minter: "0x02e0E14F84F6A07CC82E8076D09c09070B087AFf",
30 | multisig: "0xA41eC45f1828bD1b3e91Ca31Bf005AfeA540D6f2"
31 | },
32 | matic: {
33 | minter: "0xCBCe11BCFde0377b79A83a8c358743A46fb2EaF4",
34 | multisig: "0x1976b603d73eD45154473d04f44bd9f7f26ee512",
35 | admin: "0x12F421Ffac3B16c7FF73bC82f694550Fa4D711C6"
36 | },
37 | metadium: {
38 | vault: "0x292A00F3b99e3CB9b324EdbaA92258C3C61b55ab",
39 | multisig: "0x218c6E663e43542d90E4Bf6247b1E9e719ce0FAF",
40 | admin: "0x70cf20911fb49974532dc4EC8b56f96DA34511F4"
41 | },
42 | ton: {
43 | minter: "EQChjxYqk_fq_fz3QiUdu27fHEiu0ZbGuN2TF0f0vVFDZLqB",
44 | multisig: "EQBuMD8iUYs8WrGky-DmHenxi5urcXgQ7kMO2w1v-OMuZKlb",
45 | },
46 | wemix: {
47 | minter: "0xa70a4c074B93136405100FC6004cc27bDE16f602",
48 | multisig: "0x8e2cFeb906b293b329d3017eB55faff0EA0C6FF4",
49 | admin: "0x4eD917b4c9abda373d6CfcDE7Cc62c9b8beca494"
50 | },
51 | governance: {
52 | chain: "METADIUM",
53 | address: "0x292A00F3b99e3CB9b324EdbaA92258C3C61b55ab",
54 | bytes: "0x292A00F3b99e3CB9b324EdbaA92258C3C61b55ab",
55 | id: "0xb835fb9684ac2ae102c51d53fd4e14a2b08e7fd163d7a6b1d59ad70cfd6c0c36"
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/config/prod/silicon.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // operating chain list
3 | chain_list: [
4 | 'silicon',
5 | 'klaytn',
6 | 'icon',
7 | 'avax',
8 | 'bsc',
9 | 'matic',
10 | 'ton',
11 | 'wemix'
12 | ],
13 |
14 | // Bridge Addresses
15 | bridge_address: {
16 | silicon: {
17 | vault: "0x5aAAcf28ECDd691b4a657684135d8848d38236Bb",
18 | multisig: "0x67fAD8dd49abcc129DC25DE15bA1D3994F748AE5",
19 | admin: "0x3A054a90be288B75AEfa540f9Fff9B63d048dE5b"
20 | },
21 | avax: {
22 | minter: "0x6BD8E3beEC87176BA9c705c9507Aa5e6F0E6706f",
23 | multisig: "0xFA9c34485c3a706725130E8e0217431AC000E31e",
24 | admin: "0xe62Fa6C59AD14B46d4e7791FA817030732953b79",
25 | },
26 | bsc: {
27 | minter: "0x6BD8E3beEC87176BA9c705c9507Aa5e6F0E6706f",
28 | multisig: "0xFA9c34485c3a706725130E8e0217431AC000E31e",
29 | admin: "0xe62Fa6C59AD14B46d4e7791FA817030732953b79",
30 | },
31 | icon: {
32 | minter: "cx0eb215b6303142e37c0c9123abd1377feb423f0e",
33 | multisig: "cxa032c913d5d9b7577e2b19f39d91985e5c260577",
34 | },
35 | klaytn: {
36 | minter: "0x60070F5D2e1C1001400A04F152E7ABD43410F7B9",
37 | multisig: "0x74bB62c446c592a5A8424d4f9437242df1e26BF0",
38 | },
39 | matic: {
40 | minter: "0x6BD8E3beEC87176BA9c705c9507Aa5e6F0E6706f",
41 | multisig: "0xFA9c34485c3a706725130E8e0217431AC000E31e",
42 | admin: "0xe62Fa6C59AD14B46d4e7791FA817030732953b79",
43 | },
44 | ton: {
45 | minter: "EQCVcKobt9eK6KgKdpkVp_xK23My7U0DHJUrko_WuH5dm_qu",
46 | multisig: "EQDeOV9RZZA4dwS39S0YWQbmsEEfjxIT7F0BhylWTqL9jLiD",
47 | },
48 | wemix: {
49 | minter: "0x6BD8E3beEC87176BA9c705c9507Aa5e6F0E6706f",
50 | multisig: "0xCeBB82777bfe09c65AA47E8dD09a2f3972467901",
51 | admin: "0xe62Fa6C59AD14B46d4e7791FA817030732953b79",
52 | },
53 | governance: {
54 | chain: "SILICON",
55 | address: "0x5aAAcf28ECDd691b4a657684135d8848d38236Bb",
56 | bytes: "0x5aAAcf28ECDd691b4a657684135d8848d38236Bb",
57 | id: "0xaf3aa751581952cd44ce699915c6a0dd1b5df9b832505b2629420e87d1ddf981",
58 | },
59 | }
60 | }
--------------------------------------------------------------------------------
/config/prod/system.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | ethGasPriceApi: 'https://ethgasstation.info/json/ethgasAPI.json',
3 | maticGasPriceApi: 'https://gasstation-mainnet.matic.network/',
4 | ethConfirmCount: 24,
5 | klaytnConfirmCount: 10,
6 | iconConfirmCount: 4,
7 | bscConfirmCount: 15,
8 | hecoConfirmCount: 20,
9 | maticConfirmCount: 300,
10 | celoConfirmCount: 4,
11 | tonConfirmCount: 12,
12 | logLevel: 'debug'
13 | };
14 |
--------------------------------------------------------------------------------
/config/prod/ton.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | chain_list: [
3 | "avax",
4 | "bsc",
5 | "eth",
6 | "klaytn",
7 | "matic",
8 | "eth",
9 | "ton_layer_1",
10 | "silicon",
11 | ],
12 | silicon: {
13 | addressbook: "0xd0B3ac7326FDf78DEc838451E031cf69933F6faF",
14 | multisig: "0x2baF90197b3C034282Dd6cdC29a9902B7f8789A4",
15 | },
16 | // Bridge Addresses
17 | bridge_address: {
18 | ton: {
19 | vault: "EQDXbWI3jClPS510by25zTA8SUKMa4XSD2K7DbZb0jincPGw",
20 | multisig: "EQB8mNTgoG5QxqhOdVFi6X0MOjkmGNd33ct-RGBT9ZT5oDAX",
21 | },
22 | avax: {
23 | minter: "0x58A42330c0984babD5DEc2C943eAA345B7f41e44",
24 | multisig: "0x4dd5c30ae4a140d3B9180c778bD2e74c8e64E38A",
25 | admin: "0x8966c07b38dcb277f1e5264368Cafb289DBCab4f",
26 | },
27 | bsc: {
28 | minter: "0x58A42330c0984babD5DEc2C943eAA345B7f41e44",
29 | multisig: "0x4dd5c30ae4a140d3B9180c778bD2e74c8e64E38A",
30 | admin: "0x8966c07b38dcb277f1e5264368Cafb289DBCab4f",
31 | },
32 | eth: {
33 | minter: "0x5Cc6a1Dc39E523eFd6C42534a478942Cadd24f8C",
34 | multisig: "0x4dd5c30ae4a140d3B9180c778bD2e74c8e64E38A",
35 | admin: "0x8966c07b38dcb277f1e5264368Cafb289DBCab4f",
36 | },
37 | klaytn: {
38 | minter: "0x58A42330c0984babD5DEc2C943eAA345B7f41e44",
39 | multisig: "0x4dd5c30ae4a140d3B9180c778bD2e74c8e64E38A",
40 | },
41 | matic: {
42 | minter: "0x58A42330c0984babD5DEc2C943eAA345B7f41e44",
43 | multisig: "0x4dd5c30ae4a140d3B9180c778bD2e74c8e64E38A",
44 | admin: "0x8966c07b38dcb277f1e5264368Cafb289DBCab4f",
45 | },
46 | silicon: {
47 | minter: "0x4358fFeDCAE2e0BC7F21F2aF882bB1d723e30069",
48 | multisig: "0x2baF90197b3C034282Dd6cdC29a9902B7f8789A4",
49 | admin: "0x0461393F1cC22dE0E25939920Dceb798a94bb405",
50 | },
51 | governance: {
52 | chain: "TON_LAYER_1",
53 | address: "EQDXbWI3jClPS510by25zTA8SUKMa4XSD2K7DbZb0jincPGw",
54 | bytes: "0xd76d62378c294f4b9d746f2db9cd303c49428c6b85d20f62bb0db65bd238a770",
55 | id: "0x0925ffa9907f762541218b8a1b7a76ada0effdc7354d5dfbaace28d6f7ffae6d",
56 | },
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/config/prod/wemix.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // operating chain list
3 | chain_list: [
4 | "eth",
5 | "klaytn",
6 | "avax",
7 | "bsc",
8 | "matic",
9 | "metadium",
10 | "ton",
11 | "wemix",
12 | "silicon",
13 | ],
14 |
15 | // Bridge Addresses
16 | bridge_address: {
17 | avax: {
18 | minter: "0x81aB59F77cdb158d4A9DcF66d5e04E6e277a0a43",
19 | multisig: "0x56D9c7A23CBaf1442fBDaAA3B97502f089cfecbF",
20 | admin: "0x86c462C9F64347FC1b1aA43eE5dcBCEFc0Ca5514"
21 | },
22 | bsc: {
23 | minter: "0xeA74a390Df39080c417DA23023cAa84f6Bb28568",
24 | multisig: "0x41A307A2EEC05d7E8BbA452c1D061398bE29e4f6",
25 | admin: "0x81aB59F77cdb158d4A9DcF66d5e04E6e277a0a43"
26 | },
27 | eth: {
28 | minter: "0x34c51c0cD541CAddcb71dB298Ec9fAf6D0256808",
29 | multisig: "0x381A07875D7C346E024cF4a9C46616154dFd1ea5",
30 | admin: "0x8e2cFeb906b293b329d3017eB55faff0EA0C6FF4"
31 | },
32 | klaytn: {
33 | minter: "0x3be51C9F0584Cc24eA330665010d69a21edee240",
34 | multisig: "0x4A6A0c1b6452a3a4adB5F095A65BE59Eb1edd3dD"
35 | },
36 | matic: {
37 | minter: "0xb5f76BDd8383A079a31381DcD5205Bf221B6476e",
38 | multisig: "0x3f5beBAf2A10326e5aB91777a0E23E2b68E4A17c",
39 | admin: "0x4A6A0c1b6452a3a4adB5F095A65BE59Eb1edd3dD"
40 | },
41 | metadium: {
42 | minter: "0xeA74a390Df39080c417DA23023cAa84f6Bb28568",
43 | multisig: "0x41A307A2EEC05d7E8BbA452c1D061398bE29e4f6",
44 | admin: "0x81aB59F77cdb158d4A9DcF66d5e04E6e277a0a43"
45 | },
46 | ton: {
47 | minter: "EQA4XgASzx1VSi6T0r8tv1XdHwfUEplQhjg1q09RUd8gcPhd",
48 | multisig: "EQAj33y_sRp4Ypuz8zdSGfrhYdTgW1uLhjVHuUNBNxnOA1RW",
49 | },
50 | wemix: {
51 | vault: "0x445F863df0090f423A6D7005581e30d5841e4D6d",
52 | multisig: "0x775b772Bd879931433C95047aF46113E97083614",
53 | admin: "0x9CE4E2B920DdEe58158704A47650a13123907749"
54 | },
55 | silicon: {
56 | minter: "0xc8ab468c4F94E954acC2D60a328DEd74bF315CB6",
57 | multisig: "0xe938Ff16C04C06E04AEF710F7682b437D9d47065",
58 | admin: "0x18d8037c2F2af01B5eA232175E051910C0d01812"
59 | },
60 | governance: {
61 | chain: "WEMIX",
62 | address: "0x445F863df0090f423A6D7005581e30d5841e4D6d",
63 | bytes: "0x445F863df0090f423A6D7005581e30d5841e4D6d",
64 | id: "0x186eb827d7996bd507fef5bd466a5348258c6a0b0dcaeed907df7699579f363c"
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/config/prod/xrp.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // operating chain list
3 | chain_list: [
4 | 'klaytn',
5 | 'xrp',
6 | 'avax',
7 | 'bsc',
8 | 'matic',
9 | "wemix",
10 | 'silicon',
11 | ],
12 | silicon: {
13 | xrpBridge: "0x83bca9503D7888F2eFcDF18cCa2E79f8Ba75d17c",
14 | addressbook: "0x37CE54AFB91F3645b3e7455Cb4C5028507D6aBeB",
15 | multisig: "0xCe303B5740C70fFe4477E0d21E3B35770587F3B1",
16 | },
17 | // Bridge Addresses
18 | bridge_address: {
19 | avax: {
20 | minter: "0xE38ca00A6FD34B793012Bb9c1471Adc4E98386cF",
21 | multisig: "0xfa50391705D2FA7ac47Dd211B78378825bc763e6",
22 | admin: "0x009071058740276327A393B084eC447b8F0Fc6Ae",
23 | },
24 | klaytn: {
25 | minter: "0x917655B6C27A3D831b4193CE18ECe6bfcC806BF8",
26 | multisig: "0x22Bef83bABcC1169855D748D13523CA10aD87dF7",
27 | },
28 | bsc: {
29 | minter: "0xE38ca00A6FD34B793012Bb9c1471Adc4E98386cF",
30 | multisig: "0xfa50391705D2FA7ac47Dd211B78378825bc763e6",
31 | admin: "0x009071058740276327A393B084eC447b8F0Fc6Ae",
32 | },
33 | matic: {
34 | minter: "0xE38ca00A6FD34B793012Bb9c1471Adc4E98386cF",
35 | multisig: "0xfa50391705D2FA7ac47Dd211B78378825bc763e6",
36 | admin: "0x009071058740276327A393B084eC447b8F0Fc6Ae",
37 | },
38 | wemix: {
39 | minter: "0x3fc270534bBEEF400777B587D03fc66D8Ddd716E",
40 | multisig: "0x60D85ED151CBdE337019263A54AD2fb6b495547C",
41 | admin: "0xC9bD6dE100b923C275e74dC75F895B50c7488eD3",
42 | },
43 | silicon: {
44 | minter: "0x065BaE5639EB5718E0F76B27967f582e4b7d63a8",
45 | multisig: "0xCe303B5740C70fFe4477E0d21E3B35770587F3B1",
46 | admin: "0x478172a50906CaC395F8567a8dC001c7EeCB2A0A",
47 | },
48 | governance: {
49 | chain: "XRP",
50 | address: "rJTEBWu7u1NcJAiMQ9iEa1dbsuPyhTiW23",
51 | bytes: "0x00bf70ca91c426e78c28f0fa724e679d50ac59f9378a71efbd",
52 | id: "0x4f1d4170def98e5be4eb9a487615c2e39939c184839448e44096bafc42f5ee65",
53 | },
54 | }
55 | }
--------------------------------------------------------------------------------
/lib/api.js:
--------------------------------------------------------------------------------
1 | const request = require('request');
2 | const req = require("request-promise");
3 | const config = require(ROOT + '/config');
4 | const { VALIDATOR_MONITOR } = require(`${ROOT}/config/${process.env.PROFILE}/endpoints.js`);
5 |
6 | module.exports = {
7 | ethGasPrice: {
8 | request() {
9 | return new Promise((resolve, reject) => {
10 | let options = {
11 | method: 'GET',
12 | url: config.system.ethGasPriceApi
13 | };
14 |
15 | sendGetGasPrice(options, resolve, reject);
16 | })
17 | }
18 | },
19 | maticGasPrice: {
20 | request() {
21 | return new Promise((resolve, reject) => {
22 | let options = {
23 | method: 'GET',
24 | url: config.system.maticGasPriceApi
25 | };
26 |
27 | sendGetGasPrice(options, resolve, reject);
28 | })
29 | }
30 | },
31 | bible: {
32 | get(path, params = {}) {
33 | if (!VALIDATOR_MONITOR || !VALIDATOR_MONITOR.ozys || !VALIDATOR_MONITOR.ozys.bible) {
34 | return new Promise((_, reject) => {
35 | reject(new Error(`Bible Endpoint missing.`));
36 | });
37 | }
38 | let bible = VALIDATOR_MONITOR.ozys.bible;
39 | if (bible.endsWith('/')) {
40 | bible = bible.substring(0, bible.length-1);
41 | }
42 | if (path.startsWith('/')) {
43 | path = path.substring(1);
44 | }
45 | return req.get(`${bible}/${path}`, {
46 | qs: params,
47 | headers: {
48 | 'User-Agent': 'Request-Promise',
49 | },
50 | json: true,
51 | });
52 | },
53 | },
54 | validator: {
55 | post(path, params = {}) {
56 | if (!VALIDATOR_MONITOR || !VALIDATOR_MONITOR.ozys || !VALIDATOR_MONITOR.ozys.validator) {
57 | return new Promise((_, reject) => {
58 | reject(new Error(`Validator Endpoint missing.`));
59 | });
60 | }
61 | let validator = VALIDATOR_MONITOR.ozys.validator;
62 | if (validator.endsWith('/')) {
63 | validator = validator.substring(0, validator.length-1);
64 | }
65 | if (path.startsWith('/')) {
66 | path = path.substring(1);
67 | }
68 | return req.post({
69 | headers: {'User-Agent': 'Request-Promise'},
70 | url: `${validator}/${path}`,
71 | body: params,
72 | json: true
73 | })
74 | }
75 | },
76 | orbit: {
77 | get(path, params = {}) {
78 | if (!VALIDATOR_MONITOR || !VALIDATOR_MONITOR.ozys || !VALIDATOR_MONITOR.ozys.orbit) {
79 | return new Promise((_, reject) => {
80 | reject(new Error(`Orbit Endpoint missing.`));
81 | });
82 | }
83 | let orbit = VALIDATOR_MONITOR.ozys.orbit;
84 | if (orbit.endsWith('/')) {
85 | orbit = orbit.substring(0, orbit.length-1);
86 | }
87 | if (path.startsWith('/')) {
88 | path = path.substring(1);
89 | }
90 | return req.get(`${orbit}/${path}`, {
91 | qs: params,
92 | headers: {
93 | 'User-Agent': 'Request-Promise',
94 | },
95 | json: true,
96 | });
97 | },
98 | }
99 | };
100 |
101 | function sendGetGasPrice(options, resolve, reject) {
102 | options.timeout = 1000 * 30;
103 |
104 | request(options, async (error, response, body) => {
105 | if (error) {
106 | logger.error('API call error: Request error. / req: ' + JSON.stringify(options) + ' / err: ' + JSON.stringify(error));
107 | return reject(error);
108 | }
109 |
110 | let json;
111 | try {
112 | if (typeof body === 'string' || body instanceof String)
113 | json = JSON.parse(body);
114 | else
115 | json = body;
116 | } catch (e) {
117 | logger.error('API call error: JSON Parse error. / req: ' + JSON.stringify(options) + ' / err: ' + e.message);
118 | return reject(e);
119 | }
120 |
121 | if (!json) {
122 | logger.error('API returns malformed json. / req: ' + JSON.stringify(options));
123 | return reject({message: 'API returns malformed json.'});
124 | } else if (!json.fast) {
125 | logger.error('API call error: API returns fail. / req: ' + JSON.stringify(options) + ' / err: ' + JSON.stringify(json));
126 | return reject({message: 'API returns fail. ' + JSON.stringify(json)});
127 | }
128 |
129 | resolve(json);
130 | });
131 | }
132 |
--------------------------------------------------------------------------------
/lib/bridgeutils.js:
--------------------------------------------------------------------------------
1 | const bech32 = require('bech32');
2 | const rippleAddr = require('ripple-address-codec');
3 | const config = require(ROOT + '/config');
4 | const settings = config.settings;
5 | const Endpoints = config.endpoints.endpoints;
6 | const { AddressVersion, addressFromVersionHash, addressToString } = require("@stacks/transactions");
7 | const request = require("request-promise");
8 |
9 | class BridgeUtils {
10 | str2hex(input){
11 | if (typeof(input) !== 'string'){
12 | return "";
13 | }
14 |
15 | if (input.length < 2 || input.slice(0,2) !== '0x'){
16 | return '0x' + Buffer.from(input).toString('hex');
17 | }
18 |
19 | return input;
20 | }
21 |
22 | hex2str(input){
23 | input = input || ''
24 | return Buffer.from(input.replace('0x', ''), 'hex').toString('utf8');
25 | }
26 |
27 | isValidData(toChain, data) {
28 | if (!toChain)
29 | return false;
30 |
31 | if (!data)
32 | return false;
33 |
34 | if (toChain === "XRP"){
35 | return data === "0x" || parseInt(data) <= 4294967295;
36 | }
37 |
38 | return true;
39 | }
40 |
41 | isValidAddress(toChain, address) {
42 | if (!address)
43 | return false;
44 |
45 | if (!toChain)
46 | return false;
47 | toChain = toChain.toUpperCase()
48 |
49 | const EVM_CHAINS = [
50 | "ETH",
51 | "KLAYTN",
52 | "BSC",
53 | "HECO",
54 | "MATIC",
55 | "CELO",
56 | "AVAX",
57 | "FANTOM",
58 | "OEC",
59 | "XDAI",
60 | "WEMIX",
61 | "METADIUM",
62 | "SILICON"
63 | ]
64 |
65 | if (EVM_CHAINS.includes(toChain)) {
66 | return address.slice(0,2) === '0x' && address.length == 42;
67 | }
68 |
69 | if(toChain === "ICON"){
70 | let govInfo = config.governance;
71 | if(govInfo.chain === "ICON" && address.toLowerCase() === govInfo.bytes.toLowerCase()){
72 | return false;
73 | }
74 |
75 | return (address.slice(0,4) === '0x00' || address.slice(0,4) === '0x01') && address.length == 44;
76 | }
77 |
78 | if(toChain === "XRP"){
79 | let govInfo = config.governance;
80 |
81 | try{
82 | let buf = Buffer.from(address.replace('0x', ''), 'hex');
83 | address = rippleAddr.codec.codec.encode(buf);
84 | }catch(e) {
85 | return false;
86 | }
87 |
88 | return rippleAddr.isValidClassicAddress(address) && govInfo.chain === "XRP" && address.toLowerCase() !== govInfo.address.toLowerCase();
89 | }
90 |
91 | if (toChain.includes("STACKS")) {
92 | if(address.length != 42) {
93 | return false;
94 | }
95 |
96 | let addr;
97 | try {
98 | if(Endpoints.stacks.network === "testnet"){
99 | addr = addressToString(addressFromVersionHash(AddressVersion.TestnetSingleSig, address.replace("0x", "")));
100 | return addr.slice(0,2) === "ST";
101 | }
102 | else{
103 | addr = addressToString(addressFromVersionHash(AddressVersion.MainnetSingleSig, address.replace("0x", "")));
104 | return addr.slice(0,2) === "SP";
105 | }
106 | } catch(e) {
107 | return false;
108 | }
109 | }
110 |
111 | if(toChain.includes("TON")){
112 | return address.slice(0,2) === "0x" && address.length == 66;
113 | }
114 |
115 | return false;
116 | }
117 |
118 | padLeft(data, length) {
119 | return '0x' + data.replace('0x','').padStart(length,'0');
120 | }
121 |
122 | async checkTransaction(nodeConfig, data, functionSig) {
123 | const txhash = data.bytes32s[1];
124 | const CHAIN = nodeConfig.peggingType.toUpperCase();
125 | const CONFIRM_CNT = config.endpoints[CHAIN.split("_")[0].toLowerCase()].confirm || 10;
126 |
127 | const block = await nodeConfig.web3.eth.getBlock("latest").catch(e => {
128 | logger.info(`[${CHAIN}] getBlock fail: ${e.message}`);
129 | });
130 | if (!block) {
131 | return;
132 | }
133 | const tx = await nodeConfig.web3.eth.getTransactionReceipt(txhash).catch(e => {
134 | logger.info(`[${CHAIN}] getTransaction fail: ${txhash}, ${e.message}`);
135 | });
136 | if (!tx) {
137 | return;
138 | }
139 |
140 | // CHECK RELAY BLOCK CONFIRM
141 | if (block.number < tx.blockNumber + CONFIRM_CNT) {
142 | logger.info(`[${CHAIN}] TX: ${txhash}, ${block.number}, ${tx.blockNumber}. prematured.`);
143 | return;
144 | }
145 |
146 | // CHECK ADDRESS
147 | for (const log of tx.logs) {
148 | if (nodeConfig.address.toLowerCase() === log.address.toLowerCase()) {
149 | let receipt = nodeConfig.contract._decodeEventABI.bind({
150 | name: "ALLEVENTS",
151 | jsonInterface: nodeConfig.contract._jsonInterface
152 | })(log);
153 | if(receipt.event !== functionSig) continue;
154 | if(receipt.transactionHash.toLowerCase() != txhash ||
155 | receipt.returnValues.amount.toLowerCase() !== data.uints[0] ||
156 | receipt.returnValues.decimal.toLowerCase() !== (data.uints[1]).toString() ||
157 | receipt.returnValues.token.toLowerCase() !== data.token
158 | ) continue;
159 | return true;
160 | }
161 | }
162 | logger.info(`[${CHAIN}] TX: ${txhash}, ${nodeConfig.address}. governance not matched.`);
163 | }
164 |
165 | async getBeaconBlock() {
166 | const info = config.info.eth;
167 | if(!info) return;
168 |
169 | const beacon = info.ENDPOINT.beacon || "https://beacon.chain-node.orbitchain.io:7643";
170 | let res;
171 | try {
172 | res = await request.get(`${beacon}/eth/v2/beacon/blocks/finalized`);
173 | res = JSON.parse(res);
174 | } catch (e) {console.log(e);}
175 |
176 | return res;
177 | }
178 | }
179 |
180 | module.exports = BridgeUtils;
181 |
--------------------------------------------------------------------------------
/lib/decimal.js:
--------------------------------------------------------------------------------
1 | // Object.assign polyfill
2 | const BigNumber = require("bignumber.js");
3 | const PREC = 32;
4 |
5 | if (typeof Object.assign != 'function') {
6 | (function () {
7 | Object.assign = function (target) {
8 | 'use strict';
9 | if (target === undefined || target === null) {
10 | throw new TypeError('Cannot convert undefined or null to object');
11 | }
12 |
13 | var output = Object(target);
14 | for (var index = 1; index < arguments.length; index++) {
15 | var source = arguments[index];
16 | if (source !== undefined && source !== null) {
17 | for (var nextKey in source) {
18 | if (source.hasOwnProperty(nextKey)) {
19 | output[nextKey] = source[nextKey];
20 | }
21 | }
22 | }
23 | }
24 | return output;
25 | };
26 | })();
27 | }
28 |
29 | // String.repeat polyfill
30 | if (!String.prototype.repeat) {
31 | String.prototype.repeat = function(count) {
32 | 'use strict';
33 | if (this == null) {
34 | throw new TypeError('can\'t convert ' + this + ' to object');
35 | }
36 | var str = '' + this;
37 | count = +count;
38 | if (count != count) {
39 | count = 0;
40 | }
41 | if (count < 0) {
42 | throw new RangeError('repeat count must be non-negative');
43 | }
44 | if (count == Infinity) {
45 | throw new RangeError('repeat count must be less than infinity');
46 | }
47 | count = Math.floor(count);
48 | if (str.length == 0 || count == 0) {
49 | return '';
50 | }
51 | // Ensuring count is a 31-bit integer allows us to heavily optimize the
52 | // main part. But anyway, most current (August 2014) browsers can't handle
53 | // strings 1 << 28 chars or longer, so:
54 | if (str.length * count >= 1 << 28) {
55 | throw new RangeError('repeat count must not overflow maximum string size');
56 | }
57 | var rpt = '';
58 | for (var i = 0; i < count; i++) {
59 | rpt += str;
60 | }
61 | return rpt;
62 | }
63 | }
64 |
65 | String.prototype.dclean = function(){ // 불필요한 0 제거
66 | var v = this.toString();
67 | var dot = v.indexOf('.'); if(dot === -1) dot = v.length;
68 | var num = v.substr(0, dot), dec = v.substr(dot + 1);
69 |
70 | num = num.replace(/^0+/, '');
71 | if(num.length === 0) num = '0';
72 |
73 | dec = dec.replace(/0+$/, '');
74 | if(dec.length > 0) num += '.' + dec;
75 |
76 | return num;
77 | }
78 |
79 | String.prototype.dprec = function(d){ // 강제로 소수점 이하 d자리 출력
80 | var v = this.toString().dclean();
81 | var dot = v.indexOf('.'); if(dot === -1) dot = v.length;
82 | var num = v.substr(0, dot), dec = v.substr(dot + 1);
83 |
84 | if(dec.length > d) dec = dec.substr(0, d);
85 | else dec += '0'.repeat(d - dec.length);
86 |
87 | if(d > 0) num += '.' + dec;
88 |
89 | return num;
90 | }
91 |
92 | String.prototype.dmove = function(d){ // 10^d 곱함
93 | var v = this.toString().dclean();
94 | var dot = v.indexOf('.'); if(dot === -1) dot = v.length;
95 | var num = v.substr(0, dot), dec = v.substr(dot + 1);
96 |
97 | d -= dec.length; num += dec;
98 | var l = num.length;
99 |
100 | if(d > 0) num += '0'.repeat(d);
101 | else if(d < 0){
102 | d = -d;
103 | if(d < l) num = num.substr(0, l - d) + '.' + num.substr(l - d);
104 | else num = '0.' + '0'.repeat(d - l) + num;
105 | }
106 | return num.dclean();
107 | }
108 |
109 | function dton(v, w){
110 | v = v.dclean();
111 | var vt = v.indexOf('.'); if(vt === -1) vt = v.length;
112 | var vd = v.substr(vt + 1).length;
113 |
114 | w = w.dclean();
115 | var wt = w.indexOf('.'); if(wt === -1) wt = w.length;
116 | var wd = w.substr(wt + 1).length;
117 |
118 | var d = (vd > wd ? vd : wd);
119 |
120 | return { d : d, v : v.dmove(d), w : w.dmove(d) };
121 | }
122 |
123 | String.prototype.dcomp = function(w){
124 | var o = dton(this.toString(), w);
125 | var d = o.d, v = o.v; w = o.w;
126 |
127 | var vl = v.length, wl = w.length;
128 |
129 | return (vl > wl ? 1 : vl < wl ? -1 : v > w ? 1 : v < w ? -1 : 0);
130 | }
131 |
132 | String.prototype.dadd = function(w){
133 | var o = dton(this.toString(), w);
134 | var d = o.d, v = o.v; w = o.w;
135 |
136 | var vl = v.length, wl = w.length, l = (vl > wl ? vl : wl);
137 |
138 | v = v.split('').reverse().join('');
139 | w = w.split('').reverse().join('');
140 |
141 | var res = [], x = 0;
142 |
143 | for(var i = 0; i < l; i++){
144 | var vi = (i < vl ? v.charCodeAt(i) - 48 : 0);
145 | var wi = (i < wl ? w.charCodeAt(i) - 48 : 0);
146 |
147 | var r = vi + wi + x;
148 | if(r > 9){ x = 1; r -= 10; } else x = 0;
149 |
150 | res.push(r);
151 | }
152 |
153 | if(x > 0) res.push(x);
154 |
155 | return res.reverse().join('').dmove(-d);
156 | }
157 |
158 | String.prototype.dsub = function(v, prec = PREC) {
159 | const ba = new BigNumber(this);
160 | const bb = new BigNumber(String(v));
161 | return ba.minus(bb).toFixed(prec).dclean();
162 | }
163 |
164 | String.prototype.dmul = function(w){
165 | var o = dton(this.toString(), w);
166 | var d = o.d, v = o.v; w = o.w;
167 |
168 | var vl = v.length, wl = w.length, l = vl + wl - 1;
169 |
170 | v = v.split('').reverse().join('');
171 | w = w.split('').reverse().join('');
172 |
173 | var res = []; for(var i = 0; i < l; i++) res.push(0);
174 |
175 | for(var i = 0; i < vl; i++){
176 | for(var j = 0; j < wl; j++){
177 | var vi = v.charCodeAt(i) - 48;
178 | var wi = w.charCodeAt(j) - 48;
179 |
180 | res[i + j] += vi * wi;
181 | }
182 | }
183 |
184 | for(var i = 0; i < l; i++){
185 | if(res[i] < 10) continue;
186 |
187 | var x = Math.floor(res[i] / 10);
188 |
189 | if(i + 1 == l) res.push(x); else res[i + 1] += x;
190 | res[i] -= x * 10;
191 | }
192 |
193 | return res.reverse().join('').dmove(-2 * d);
194 | }
195 |
196 | String.prototype.ddiv = function(w, prec){
197 | prec = prec ? prec : 40
198 |
199 | if(w.dcomp('0') === 0){
200 | throw 'Error: Divide by zero';
201 | }
202 |
203 | var o = dton(this.toString(), w);
204 | var v = o.v; w = o.w;
205 |
206 | var res = '', d = 0;
207 |
208 | while(v.dcomp(w) >= 0){ w += '0'; d++; }
209 |
210 | for(var i = 1; i <= d; i++){
211 | w = w.slice(0, -1);
212 |
213 | var c = 0;
214 | while(v.dcomp(w) >= 0){ v = v.dsub(w); c++; }
215 |
216 | res += c;
217 | }
218 |
219 | res += '.';
220 |
221 | for(var i = 1; i <= prec; i++){
222 | v += '0';
223 |
224 | var c = 0;
225 | while(v.dcomp(w) >= 0){ v = v.dsub(w); c++; }
226 |
227 | res += c;
228 | }
229 |
230 | return res.dclean();
231 | }
--------------------------------------------------------------------------------
/lib/request.js:
--------------------------------------------------------------------------------
1 | var querystring = require('querystring');
2 | var libRequest = require('request');
3 |
4 | class Request {
5 | constructor(host) {
6 | if (!host.startsWith("http://") && !host.startsWith("https://"))
7 | host = "http://" + host;
8 | this.host = host;
9 | }
10 |
11 | _generalErrorHandler(next, error, response, body) {
12 | if (!error && response.statusCode == 200) {
13 | if (body.error) {
14 | next(body.error);
15 | return true;
16 | }
17 | return false;
18 | } else {
19 | next(error);
20 | return true;
21 | }
22 | }
23 |
24 | rpc(method, params, id, callback) {
25 | var headers = {
26 | 'content-type': 'application/json'
27 | };
28 |
29 | id = (id || '1').toString();
30 | var options = {
31 | url: this.host,
32 | method: 'POST',
33 | headers: headers,
34 | json: {
35 | "jsonrpc": "2.0",
36 | "id": id,
37 | "method": method,
38 | "params": params
39 | }
40 | };
41 |
42 | if (callback) {
43 | libRequest(options, function (error, response, body) {
44 | if (this._generalErrorHandler(callback, error, response, body)) {
45 | return
46 | }
47 | callback(null, body.result);
48 | });
49 | } else {
50 | return new Promise((resolve, reject) => {
51 | libRequest(options, function (error, response, body) {
52 | if (this._generalErrorHandler(reject, error, response, body)) {
53 | return
54 | }
55 | resolve(body.result);
56 | });
57 | });
58 | }
59 |
60 | }
61 |
62 | httpPost(path, json, callback) {
63 | var headers = {
64 | 'content-type': 'application/json',
65 | 'User-Agent': 'ova-request/1.0'
66 | };
67 | var options = {
68 | url: this.host + path,
69 | method: 'POST',
70 | headers: headers,
71 | json: json
72 | };
73 |
74 | if (callback) {
75 | libRequest(options, (error, response, body) => {
76 | if (this._generalErrorHandler(callback, error, response, body)) {
77 | return
78 | }
79 | callback(null, body);
80 | });
81 | } else {
82 | return new Promise((resolve, reject) => {
83 | libRequest(options, (error, response, body) => {
84 | if (this._generalErrorHandler(reject, error, response, body)) {
85 | console.log(path, json)
86 | return
87 | }
88 | resolve(body);
89 | });
90 | });
91 | }
92 | }
93 |
94 | httpGet(path, callback) {
95 | var headers = {
96 | 'User-Agent': 'ova-request/1.0'
97 | };
98 | var options = {
99 | url: this.host + path,
100 | headers: headers
101 | };
102 | if (callback) {
103 | libRequest.get(options, (error, response, body) => {
104 | if (this._generalErrorHandler(callback, error, response, body)) {
105 | return
106 | }
107 | callback(null, body);
108 | });
109 | } else {
110 | return new Promise((resolve, reject) => {
111 | libRequest.get(options, (error, response, body) => {
112 | if (this._generalErrorHandler(reject, error, response, body)) {
113 | console.log(path, error)
114 | return
115 | }
116 | resolve(body);
117 | });
118 | });
119 | }
120 | }
121 |
122 | monitor(title, message, key, error) {
123 |
124 | var form = {
125 | title: title,
126 | message: message,
127 | key: key,
128 | error: error
129 | };
130 |
131 |
132 | var formData = querystring.stringify(form);
133 | var contentLength = formData.length;
134 |
135 | libRequest({
136 | headers: {
137 | 'Content-Length': contentLength,
138 | 'Content-Type': 'application/x-www-form-urlencoded'
139 | },
140 | uri: this.host + 'api/direct',
141 | body: formData,
142 | method: 'POST'
143 | }, function (err, res, body) {
144 | if (err || !res || res.statusCode != 200 || !body) {
145 | logger.error('Monitor direct Error');
146 | logger.error(err);
147 | return;
148 | }
149 | try {
150 | var result = JSON.parse(body);
151 | if (result.result != "success") {
152 | logger.error('Monitor body Error');
153 | logger.error(body);
154 | }
155 | } catch (e) {
156 | logger.error('Monitor body Error');
157 | logger.error(body);
158 | return;
159 | }
160 |
161 |
162 | });
163 | }
164 | }
165 | module.exports = Request;
--------------------------------------------------------------------------------
/lib/rpcAggregator.js:
--------------------------------------------------------------------------------
1 | const Britto = require("./britto");
2 |
3 | Britto.setAdd0x();
4 | Britto.setRemove0x();
5 |
6 | class RPCAggregator {
7 | chainId;
8 | chainName;
9 | pool = [];
10 |
11 | constructor(_chainName, _chainId) {
12 | this.chainName = _chainName;
13 | this.chainId = _chainId;
14 | }
15 |
16 | addRpc(url, {
17 | name = "mainnet",
18 | address,
19 | abi,
20 | multisig,
21 | onconnect,
22 | } = {}) {
23 | if(this.isExist(url)) return;
24 |
25 | const node = Britto.getNodeConfigBase(name);
26 | node.rpc = url;
27 | node.address = address;
28 | node.abi = abi;
29 | global.monitor.setNodeConnectStatus(`${this.chainName}_${this.pool.length}`, node.rpc, "connecting");
30 | if (onconnect) {
31 | node.onconnect = onconnect;
32 | }
33 | new Britto(node, `${this.chainName}_${this.pool.length}`).connectWeb3();
34 | if (multisig) {
35 | node.multisig.wallet = multisig.address;
36 | node.multisig.abi = multisig.abi;
37 | node.multisig.contract = new node.web3.eth.Contract(node.multisig.abi, node.multisig.wallet);
38 | }
39 | this.pool.push(node);
40 | }
41 |
42 | async addRpcWithBritto(node) {
43 | if(this.isExist(node.rpc)) return;
44 | this.pool.push(node);
45 | let block = await node.web3.eth.getBlock("latest").catch(e => {console.log(e)});
46 | return !block ? false : true;
47 | }
48 |
49 | length() {
50 | return this.pool.length;
51 | }
52 |
53 | async select() {
54 | let bn = 0;
55 | let electedIndex;
56 |
57 | for(let i=0; i {
64 | logger.error(`[RPC_AGGREGATOR] getBlockNumber:${e}`);
65 | });
66 | if(!curBlockNumber || parseInt(curBlockNumber) < bn) {
67 | continue;
68 | }
69 |
70 | bn = parseInt(curBlockNumber);
71 | electedIndex = i;
72 | }
73 | const elected = this.pool[electedIndex];
74 | if (elected) {
75 | global.monitor.setNodeElectionStatus(elected.peggingType, elected.rpc, bn);
76 | }
77 |
78 | return elected;
79 | }
80 |
81 | async getNodes() {
82 | let arr = [...this.pool];
83 | for (let i = arr.length - 1; i > 0; i--) {
84 | let j = Math.floor(Math.random() * (i + 1));
85 | [arr[i], arr[j]] = [arr[j], arr[i]];
86 | }
87 | return arr;
88 | }
89 |
90 | async majorityCheckForDatasInRpcs(func) {
91 | const nodes = await this.getNodes();
92 | const requireCnt = parseInt(nodes.length/2) + 1;
93 | let resMap = {};
94 | for (const node of nodes) {
95 | let res = await func(node);
96 | if (!res) {
97 | continue;
98 | }
99 | res = JSON.stringify(res);
100 | if (!resMap[res]) {
101 | resMap[res] = 1;
102 | } else {
103 | resMap[res] += 1;
104 | }
105 | if (resMap[res] >= requireCnt) {
106 | return JSON.parse(res);
107 | }
108 | }
109 | }
110 |
111 | isExist(rpc) {
112 | const nodes = this.pool;
113 | return nodes.find(node => { return node.rpc.toLowerCase() === rpc.toLowerCase() });
114 | }
115 | }
116 |
117 | module.exports = RPCAggregator;
118 |
--------------------------------------------------------------------------------
/lib/txsender.js:
--------------------------------------------------------------------------------
1 | let Tx = require('ethereumjs-tx');
2 | let txutils = require('./txutils');
3 |
4 | class Txsender {
5 | static sendTransaction(nodeConfig, txData, sender, callback) {
6 | let web3 = nodeConfig.web3;
7 |
8 | if (!Buffer.isBuffer(sender.pk))
9 | sender.pk = Buffer.from(sender.pk, 'hex');
10 |
11 | let _this = this;
12 | return new Promise((resolve, reject) => {
13 | if(!txData || !txData.method || !txData.args || !txData.options)
14 | return logger.error('Invalid transaction data.');
15 | if(!sender || !sender.address || !sender.pk)
16 | return logger.error('Invalid transaction sender');
17 |
18 | let rawTx = txutils.functionTx(nodeConfig.abi, txData.method, txData.args, txData.options);
19 |
20 | let timeout = (isNaN(parseInt(sender.timeout)))? 5000 : sender.timeout;
21 |
22 | setTimeout(async () => {
23 | let nonce = await _this.getWeb3Nonce(nodeConfig.web3, sender.address).catch(e => {
24 | logger.error('sendTransaction getNonce error');
25 | logger.error(e);
26 | });
27 |
28 | if(!nonce)
29 | return;
30 |
31 | let tx = new Tx(rawTx);
32 | tx['nonce'] = sender.nonce || nonce;
33 | // for EIP 155 compute
34 | tx._chainId = txData.options.chainId || 0;
35 | try {
36 | tx.sign(sender.pk);
37 | } catch (e) {
38 | logger.error(`Cannot Sign transaction by PK(${sender.pk}))`);
39 | return;
40 | }
41 |
42 | let serializedTx = tx.serialize();
43 |
44 | logger.info('----------------[' + (nodeConfig.peggingType || '---') + ']----------------');
45 | logger.info(`Send ${(txData.method || 'Unknown')}(${txData.block || ''}) Transaction`);
46 | if (txData.info) logger.info(`Info : ${txData.info}`)
47 | logger.info(`GasPrice : ${Number(txData.options.gasPrice)}`);
48 |
49 | web3.eth.sendSignedTransaction('0x' + serializedTx.toString('hex'))
50 | .once('transactionHash', thash => {
51 | if (callback)
52 | callback(thash);
53 |
54 | resolve(thash);
55 | logger.info('Transaction sent : ' + thash);
56 | logger.info('Transaction nonce: ' + (Number(sender.nonce || nonce)));
57 | logger.info('-------------------------------------');
58 | })
59 | .once('error', e => {
60 | logger.error(`Fail to send ${txData.method} transaction(${Number(sender.nonce || nonce)}): ${e.message}`);
61 | resolve(e.message);
62 | });
63 | }, timeout)
64 | });
65 | }
66 |
67 |
68 | static getWeb3Nonce(web3, address, option, callback) {
69 | return new Promise((resolve, reject) => {
70 | web3.eth.getTransactionCount(address, option || 'pending')
71 | .then(nonce => {
72 | nonce = web3.utils.toHex(nonce);
73 |
74 | callback && callback(nonce);
75 |
76 | resolve(nonce);
77 | })
78 | .catch((e) => {
79 | console.error('getWeb3Nonce error');
80 | console.log(e);
81 | reject(e);
82 | });
83 | })
84 | }
85 | }
86 |
87 | module.exports = Txsender;
88 |
--------------------------------------------------------------------------------
/lib/txutils.js:
--------------------------------------------------------------------------------
1 | var Transaction = require('ethereumjs-tx');
2 | //var coder = require('web3/lib/solidity/coder');
3 | // When updating to web3 1.0.0, replace by
4 | var coder = require('web3-eth-abi');
5 | var rlp = require('rlp');
6 | var CryptoJS = require('crypto-js');
7 |
8 | function add0x (input) {
9 | if (typeof(input) !== 'string') {
10 | return input;
11 | }
12 | if (input.length < 2 || input.slice(0,2) !== '0x') {
13 | return '0x' + input;
14 | }
15 |
16 | return input;
17 | }
18 |
19 | function strip0x (input) {
20 | if (typeof(input) !== 'string') {
21 | return input;
22 | }
23 | else if (input.length >= 2 && input.slice(0,2) === '0x') {
24 | return input.slice(2);
25 | }
26 | else {
27 | return input;
28 | }
29 | }
30 |
31 | function _encodeFunctionTxData (functionName, types, args) {
32 |
33 | var fullName = functionName + '(' + types.join() + ')';
34 | // var signature = CryptoJS.SHA3(fullName, { outputLength: 256 }).toString(CryptoJS.enc.Hex).slice(0, 8);
35 | // var dataHex = '0x' + signature + coder.encodeParams(types, args);
36 | // When updating to web3 1.0.0, replace by
37 | var dataHex = coder.encodeFunctionSignature(fullName) + coder.encodeParameters(types, args).replace('0x','')
38 |
39 | return dataHex;
40 | }
41 |
42 | function _getTypesFromAbi (abi, functionName) {
43 |
44 | function matchesFunctionName(json) {
45 | return (json.name === functionName && json.type === 'function');
46 | }
47 |
48 | function getTypes(json) {
49 | return json.type;
50 | }
51 |
52 | var funcJson = abi.filter(matchesFunctionName)[0];
53 |
54 | return (funcJson.inputs).map(getTypes);
55 | }
56 |
57 | function functionTx (abi, functionName, args, txObject) {
58 | // txObject contains gasPrice, gasLimit, nonce, to, value
59 |
60 | var types = _getTypesFromAbi(abi, functionName);
61 | var txData = _encodeFunctionTxData(functionName, types, args);
62 |
63 | var txObjectCopy = {};
64 | txObjectCopy.to = add0x(txObject.to);
65 | txObjectCopy.gasPrice = add0x(txObject.gasPrice);
66 | txObjectCopy.gasLimit = add0x(txObject.gasLimit);
67 | txObjectCopy.nonce = add0x(txObject.nonce);
68 | txObjectCopy.data = add0x(txData);
69 | txObjectCopy.value = add0x(txObject.value);
70 |
71 | return '0x' + (new Transaction(txObjectCopy)).serialize().toString('hex');
72 | }
73 |
74 | function createdContractAddress (fromAddress, nonce) {
75 | var rlpEncodedHex = rlp.encode([new Buffer(strip0x(fromAddress), 'hex'), nonce]).toString('hex');
76 | var rlpEncodedWordArray = CryptoJS.enc.Hex.parse(rlpEncodedHex);
77 | var hash = CryptoJS.SHA3(rlpEncodedWordArray, {outputLength: 256}).toString(CryptoJS.enc.Hex);
78 |
79 | return '0x' + hash.slice(24);
80 | }
81 |
82 | function createContractTx (fromAddress, txObject) {
83 | // txObject contains gasPrice, gasLimit, value, data, nonce
84 |
85 | var txObjectCopy = {};
86 | txObjectCopy.to = add0x(txObject.to);
87 | txObjectCopy.gasPrice = add0x(txObject.gasPrice);
88 | txObjectCopy.gasLimit = add0x(txObject.gasLimit);
89 | txObjectCopy.nonce = add0x(txObject.nonce);
90 | txObjectCopy.data = add0x(txObject.data);
91 | txObjectCopy.value = add0x(txObject.value);
92 |
93 | var contractAddress = createdContractAddress(fromAddress, txObject.nonce);
94 | var tx = new Transaction(txObjectCopy);
95 |
96 | return {tx: '0x' + tx.serialize().toString('hex'), addr: contractAddress};
97 | }
98 |
99 | function valueTx (txObject) {
100 | // txObject contains gasPrice, gasLimit, value, nonce
101 |
102 | var txObjectCopy = {};
103 | txObjectCopy.to = add0x(txObject.to);
104 | txObjectCopy.gasPrice = add0x(txObject.gasPrice);
105 | txObjectCopy.gasLimit = add0x(txObject.gasLimit);
106 | txObjectCopy.nonce = add0x(txObject.nonce);
107 | txObjectCopy.value = add0x(txObject.value);
108 |
109 | var tx = new Transaction(txObjectCopy);
110 |
111 | return '0x' + tx.serialize().toString('hex');
112 | }
113 |
114 | module.exports = {
115 | _encodeFunctionTxData: _encodeFunctionTxData,
116 | _getTypesFromAbi: _getTypesFromAbi,
117 | functionTx: functionTx,
118 | createdContractAddress: createdContractAddress,
119 | createContractTx: createContractTx,
120 | valueTx: valueTx
121 | };
122 |
--------------------------------------------------------------------------------
/lib/utils.js:
--------------------------------------------------------------------------------
1 | function getEndpoint (chain) {
2 | return require(ROOT + `/config/endpoints`).endpoints[chain.toLowerCase()]
3 | }
4 |
5 | function contractAddress (layer2Chain) {
6 | let { bridge_address } = require(ROOT + `/config/${process.env.CHAIN.toLowerCase()}`)
7 | return bridge_address[layer2Chain]
8 | }
9 |
10 | function multisigAddress(migChain) {
11 | let { bridge_address } = require(ROOT + `/config/${process.env.CHAIN.toLowerCase()}`)
12 | return bridge_address[migChain].multisig
13 | }
14 |
15 | function ed25519MultisigAddress() {
16 | let { bridge_address } = require(ROOT + `/config/${process.env.CHAIN.toLowerCase()}`)
17 | return bridge_address.multisig.ton;
18 | }
19 |
20 | function isEvmAddress(address) {
21 | return address.slice(0,2) === "0x" && address.length === 42;
22 | }
23 |
24 | module.exports = {
25 | getEndpoint,
26 | contractAddress,
27 | multisigAddress,
28 | ed25519MultisigAddress,
29 | isEvmAddress
30 | }
--------------------------------------------------------------------------------
/logger.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | require(ROOT + '/lib/decimal');
4 | const winston = require('winston');
5 | const moment = require('moment');
6 | const config = require(ROOT + '/config');
7 |
8 | const tsFormat = function () {
9 | return moment().format('YYYY-MM-DD HH:mm:ss');
10 | }
11 |
12 | //////////////////////////////////////////////////////////////////////////////////////////
13 | const myFormat = winston.format.printf(info => {
14 | return tsFormat() + ' ' + info.message;
15 | });
16 |
17 | // Normal Logger: Winston
18 | let logger = winston.createLogger({
19 | level: config.system.logLevel || 'info',
20 | format: winston.format.combine(
21 | myFormat
22 | ),
23 | transports: [
24 | new(winston.transports.Console)({
25 | colorize: true,
26 | handleExceptions: true,
27 | })
28 | ]
29 | });
30 |
31 | //Promise unhandled rejection logger.
32 | //process.off('unhandledRejection', () => {});
33 | process.on('unhandledRejection', (reason, p) => {
34 | console.error('Unhandled rejection Promise: ', p, ' reason: ', reason)
35 | });
36 |
37 | module.exports = logger;
38 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "orbit-bridge-validators",
3 | "version": "2.0.1",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "@stacks/transactions": "^3.3.0",
14 | "abi-decoder": "^2.3.0",
15 | "bignumber.js": "^9.1.2",
16 | "bn.js": "^5.1.3",
17 | "bs58": "^4.0.1",
18 | "crypto-js": "^3.1.9-1",
19 | "dotenv": "^16.0.3",
20 | "elliptic": "^6.4.1",
21 | "ethereumjs-abi": "^0.6.8",
22 | "ethereumjs-tx": "^1.3.7",
23 | "ethereumjs-util": "^5.2.0",
24 | "ethereumjs-wallet": "^0.6.3",
25 | "ethers": "^5.0.7",
26 | "express": "^4.17.1",
27 | "icon-sdk-js": "^1.1.3",
28 | "lodash": "^4.17.20",
29 | "moment": "^2.28.0",
30 | "readline-sync": "^1.4.10",
31 | "request-promise": "^4.2.6",
32 | "ripple-address-codec": "4.2.3",
33 | "ripple-lib": "1.10.0",
34 | "secp256k1": "^4.0.2",
35 | "ton": "^12.0.0",
36 | "tonweb": "^0.0.52",
37 | "varuint-bitcoin": "^1.1.0",
38 | "web3": "^1.0.0-beta.37",
39 | "winston": "^3.1.0",
40 | "winston-daily-rotate-file": "^2.0.0-rc.1"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/pm2.yaml:
--------------------------------------------------------------------------------
1 | apps:
2 | - script : app.js
3 | name : 'validator'
4 | cwd : .
5 | instances : 1
6 | watch : false
7 | exec_mode : fork
8 | env :
9 | NODE_ENV : production
10 | PORT : 8984
--------------------------------------------------------------------------------
/routes/index.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const router = express.Router();
3 |
4 | router.get('/', function (req, res, next) {
5 | if(!global.monitor) {
6 | res.json("monitoring not enabled.");
7 | return;
8 | }
9 |
10 | res.json(global.monitor.json());
11 | });
12 |
13 | module.exports = router;
--------------------------------------------------------------------------------
/routes/v1/gov.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const router = express.Router();
3 | let govInstance;
4 |
5 | // http://host/v1/gov/
6 | router.get("/", function (req, res, next) {
7 | res.send("gov");
8 | });
9 |
10 | router.get("/getAddress/:chain", async function (req, res, next) {
11 | const chain = req.body && req.body.chain || req.params && req.params.chain;
12 | return res.json(await govInstance.getAddress(chain));
13 | })
14 |
15 | router.get("/getTransaction/:chain/:transactionId", async function (req, res, next) {
16 | const chain = req.body && req.body.chain || req.params && req.params.chain;
17 | const tid = req.body && req.body.transactionId || req.params && req.params.transactionId;
18 | return res.json(await govInstance.getTransaction(chain, tid));
19 | })
20 |
21 | router.get("/confirm/:chain/:transactionId/:gasPrice/:chainId", async function (req, res, next) {
22 | const chain = req.body && req.body.chain || req.params && req.params.chain;
23 | const tid = req.body && req.body.transactionId || req.params && req.params.transactionId;
24 | const gasPrice = req.body && req.body.gasPrice || req.params && req.params.gasPrice;
25 | const chainId = req.body && req.body.chainId || req.params && req.params.chainId;
26 | return res.json(await govInstance.confirmTransaction(chain, tid, gasPrice, chainId));
27 | })
28 |
29 | router.get("/confirmRange/:chain/:start/:end/:gasPrice/:chainId", async function (req, res, next) {
30 | const chain = req.body && req.body.chain || req.params && req.params.chain;
31 | const start = req.body && req.body.start || req.params && req.params.start;
32 | const end = req.body && req.body.end || req.params && req.params.end;
33 | const gasPrice = req.body && req.body.gasPrice || req.params && req.params.gasPrice;
34 | const chainId = req.body && req.body.chainId || req.params && req.params.chainId;
35 | return res.send(await govInstance.confirmTransactionByRange(chain, start, end, gasPrice, chainId));
36 | })
37 |
38 | router.get("/validate/:sigHash", async function (req, res, next) {
39 | const sigHash = req.body && req.body.sigHash || req.params && req.params.sigHash;
40 | return res.json(await govInstance.validateSigHash(sigHash));
41 | });
42 |
43 | // deprecated
44 | /*
45 | router.get("/validateEd25519/:sigHash", async function (req, res, next) {
46 | const sigHash = req.body && req.body.sigHash || req.params && req.params.sigHash;
47 | return res.json(await govInstance.validateEd25519SigHash(sigHash));
48 | });
49 | */
50 |
51 | function setGovInstance(instance) {
52 | govInstance = instance;
53 | return router;
54 | }
55 |
56 | module.exports = {
57 | setGovInstance,
58 | }
59 |
--------------------------------------------------------------------------------
/src/evm/logger.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const winston = require('winston');
4 | const moment = require('moment');
5 | const config = require(ROOT + '/config');
6 |
7 | const tsFormat = function () {
8 | return moment().format('YYYY-MM-DD HH:mm:ss');
9 | }
10 |
11 | //////////////////////////////////////////////////////////////////////////////////////////
12 | const myFormat = winston.format.printf(info => {
13 | return `[${info.chain || "EVM"}] ` + tsFormat() + ' ' + info.message;
14 | });
15 |
16 | // Normal Logger: Winston
17 | let logger = winston.createLogger({
18 | level: config.system.logLevel || 'info',
19 | format: winston.format.combine(
20 | myFormat
21 | ),
22 | transports: [
23 | new(winston.transports.Console)({
24 | colorize: true,
25 | handleExceptions: true,
26 | })
27 | ]
28 | });
29 |
30 | module.exports = logger;
31 |
--------------------------------------------------------------------------------
/src/evm/utils/packer.js:
--------------------------------------------------------------------------------
1 | exports.packRelayedData = function(data) {
2 | let result = [];
3 |
4 | result.push({t: 'string', v: data.fromChain});
5 | result.push({t: 'bytes32[]', v: data.bytes32s});
6 | result.push({t: 'uint[]', v: data.uints});
7 |
8 | return result;
9 | }
10 |
11 | exports.packChainId = function (data) {
12 | let result = [];
13 |
14 | result.push({t: 'address', v: data.hubContract});
15 | result.push({t: 'string', v:data.chain});
16 |
17 | return result;
18 | }
19 |
20 | exports.packSwapData = function(data) {
21 | let result = [];
22 |
23 | result.push({t: 'address', v: data.hubContract});
24 | result.push({t: 'string', v: data.fromChain});
25 | result.push({t: 'string', v: data.toChain});
26 | result.push({t: 'bytes', v: toHexBuffer(data.fromAddr)});
27 | result.push({t: 'bytes', v: toHexBuffer(data.toAddr)});
28 | result.push({t: 'bytes', v: toHexBuffer(data.token)});
29 | result.push({t: 'bytes32[]', v: data.bytes32s});
30 | result.push({t: 'uint[]', v: data.uints});
31 | result.push({t: 'bytes', v: toHexBuffer(data.data)});
32 |
33 | return result;
34 | };
35 |
36 | exports.packLimitationData = function(data) {
37 | let result = [];
38 |
39 | result.push({t: 'string', v: "GateKeeper"});
40 | result.push({t: 'string', v: data.fromChain});
41 | result.push({t: 'string', v: data.toChain});
42 | result.push({t: 'bytes', v: toHexBuffer(data.token)});
43 | result.push({t: 'bytes32[]', v: data.bytes32s});
44 | result.push({t: 'uint[]', v: data.uints});
45 |
46 | return result;
47 | }
48 |
49 | function toHexBuffer(str) {
50 | return Buffer.from(str.replace('0x', ""), 'hex');
51 | }
52 |
--------------------------------------------------------------------------------
/src/gov/index.js:
--------------------------------------------------------------------------------
1 | global.logger.gov = require('./logger');
2 |
3 | const config = require(ROOT + '/config');
4 | const Britto = require(ROOT + '/lib/britto');
5 | const abiDecoder = require('abi-decoder');
6 |
7 | const errmBeforeInitialize = {
8 | "errm": "Before Initialized",
9 | "data": "Error: Before Initialized"
10 | };
11 |
12 | const errmInvalidChain = (chain) => {
13 | return {
14 | "errm": "Invalid Chain",
15 | "data": `NotFoundError: Invalid Chain Name ${chain}`
16 | }
17 | };
18 |
19 | const invalidChainList = ["gov", "xrp", "stacks", "stacks_layer_1"];
20 |
21 | class Governance {
22 | constructor(){
23 | if(this.initialized)
24 | throw "Already Initialized";
25 |
26 | const ABI = Britto.getJSONInterface({filename: "Governance"});
27 | abiDecoder.addABI(ABI);
28 |
29 | this.initialized = true;
30 | }
31 |
32 | getAddress(chain) {
33 | if(!this.initialized) return errmBeforeInitialize;
34 |
35 | return monitor.address[chain.toUpperCase()];
36 | }
37 |
38 | async getTransaction(chain, transactionId) {
39 | if(!this.initialized) return errmBeforeInitialize;
40 |
41 | logger.gov.info(`GetTransaction: ${chain}, ${transactionId}`);
42 |
43 | chain = chain.toLowerCase();
44 | if(invalidChainList.includes(chain) || !instances[chain]) return errmInvalidChain(chain);
45 |
46 | const instance = instances[chain];
47 | const res = await instance.getTransaction(transactionId, abiDecoder);
48 | return res;
49 | }
50 |
51 | async confirmTransaction(chain, transactionId, gasPrice, chainId) {
52 | if(!this.initialized) return errmBeforeInitialize;
53 |
54 | chain = chain.toLowerCase();
55 | if(invalidChainList.includes(chain) || !instances[chain]) return errmInvalidChain(chain);
56 |
57 | logger.gov.info(`ConfirmTransaction: ${chain}, ${transactionId}, ${gasPrice}, ${chainId}`);
58 |
59 | const instance = instances[chain];
60 | const res = await instance.confirmTransaction(transactionId, gasPrice, chainId);
61 | return res;
62 | }
63 |
64 | async confirmTransactionByRange(chain, start, end, gasPrice, chainId) {
65 | if(!this.initialized) return errmBeforeInitialize;
66 |
67 | logger.gov.info(`ConfirmTransactionRange: ${chain}, ${start}, ${end}, ${gasPrice}, ${chainId}`);
68 |
69 | chain = chain.toLowerCase();
70 | if(invalidChainList.includes(chain) || !instances[chain]) return errmInvalidChain(chain);
71 |
72 | const instance = instances[chain];
73 |
74 | let res = [];
75 | for(let i = parseInt(start); i <= parseInt(end); i++){
76 | let txHash = await instance.confirmTransaction(i, gasPrice, chainId);
77 | res.push({
78 | transactionId: i,
79 | res: txHash
80 | })
81 | }
82 |
83 | return JSON.stringify(res, null, ' ');
84 | }
85 |
86 | async validateSigHash(sigHash) {
87 | if(!this.initialized) return errmBeforeInitialize;
88 |
89 | logger.gov.info(`ValidateSigHash: ${sigHash}`)
90 |
91 | if(sigHash.length !== 66) return "Invalid Input Hash";
92 | let signature = Britto.signMessage(sigHash, process.env.VALIDATOR_PK);
93 |
94 | return {
95 | validator: monitor.validatorAddress,
96 | sigHash,
97 | v: signature.v,
98 | r: signature.r,
99 | s: signature.s,
100 | };
101 | }
102 |
103 | // deprecated
104 | /*
105 | async validateEd25519SigHash(sigHash) {
106 | if(!this.initialized) return errmBeforeInitialize;
107 | if(!instances["orbit"]) return errmInvalidChain;
108 |
109 | logger.gov.info(`validateEd25519SigHash: ${sigHash}`)
110 |
111 | const instance = instances["orbit"];
112 | const res = await instance.validateEd25519SigHash(multisig, sigHash);
113 | return res;
114 | }
115 | */
116 | }
117 |
118 | module.exports = Governance;
119 |
--------------------------------------------------------------------------------
/src/gov/logger.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const winston = require('winston');
4 | const moment = require('moment');
5 | const config = require(ROOT + '/config');
6 |
7 | const tsFormat = function () {
8 | return moment().format('YYYY-MM-DD HH:mm:ss');
9 | }
10 |
11 | //////////////////////////////////////////////////////////////////////////////////////////
12 | const myFormat = winston.format.printf(info => {
13 | return '[GOV] ' + tsFormat() + ' ' + info.message;
14 | });
15 |
16 | // Normal Logger: Winston
17 | let logger = winston.createLogger({
18 | level: config.system.logLevel || 'info',
19 | format: winston.format.combine(
20 | myFormat
21 | ),
22 | transports: [
23 | new(winston.transports.Console)({
24 | colorize: true,
25 | handleExceptions: true,
26 | })
27 | ]
28 | });
29 |
30 | module.exports = logger;
--------------------------------------------------------------------------------
/src/hub/index.js:
--------------------------------------------------------------------------------
1 | global.logger.hub = require('./logger');
2 |
3 | const config = require(ROOT + '/config');
4 | const Britto = require(ROOT + '/lib/britto');
5 |
6 | const packer = require("./utils/packer");
7 |
8 | class OrbitHub {
9 | constructor(chainList) {
10 | if(!chainList || chainList.length === 0){
11 | throw Error("Invalid chainList");
12 | }
13 | this.chainList = chainList;
14 |
15 | const chainName = this.chainName = "HUB";
16 | this.lastBlockNum = null;
17 |
18 | const govInfo = this.govInfo = config.governance;
19 | if(!govInfo || !govInfo.chain || !govInfo.address || !govInfo.bytes || !govInfo.id) {
20 | throw Error('Empty Governance Info');
21 | }
22 |
23 | const info = config.info.orbit;
24 |
25 | const orbitHub = this.orbitHub = Britto.getNodeConfigBase('orbitHub');
26 | orbitHub.ws = info.ENDPOINT.socket;
27 | orbitHub.rpc = info.ENDPOINT.rpc;
28 | orbitHub.address = info.CONTRACT_ADDRESS.OrbitHubContract;
29 | orbitHub.abi = Britto.getJSONInterface({filename: 'OrbitHub'});
30 | orbitHub.gateKeeperABI = Britto.getJSONInterface({filename: 'GateKeeper'});
31 |
32 | this.eventList = [
33 | {
34 | name: 'SwapRelay',
35 | callback: this.receiveSwapRelay.bind(this),
36 | },
37 | {
38 | name: 'SwapNFTRelay',
39 | callback: this.receiveSwapNFTRelay.bind(this),
40 | }
41 | ];
42 |
43 | orbitHub.onconnect = () => {
44 | this.setChainIds(chainList);
45 | this.startSubscription(orbitHub, this.eventList);
46 | };
47 |
48 | orbitHub.ondisconnect = () => {
49 | logger.hub.info(`On disconnected: clear ${orbitHub.ws} subscription !`);
50 | orbitHub.web3.eth.clearSubscriptions();
51 | };
52 |
53 | global.monitor.setNodeConnectStatus(chainName, orbitHub.ws, "connecting");
54 | new Britto(orbitHub, chainName).connectWeb3();
55 |
56 | this.hashMap = new Map();
57 | this.flushHashMap();
58 |
59 | this.chainIds = {};
60 | this.subscribers = [];
61 | }
62 |
63 | registerSubscriber(node, eventList) {
64 | this.subscribers.push({node, eventList});
65 | }
66 |
67 | startSubscription(node, eventList) {
68 | this.subscribeNewBlock(node.web3, blockNumber => {
69 | global.monitor.setBlockNumber(this.chainName, blockNumber);
70 | this.getPastLogs(blockNumber, node, eventList);
71 | });
72 | }
73 |
74 | subscribeNewBlock(web3, callback) {
75 | web3.eth.subscribe('newBlockHeaders', (err, res) => {
76 | if (err)
77 | return logger.hub.error('subscribeNewBlock subscribe error: ' + err.message);
78 |
79 | if (!res.number) {
80 | return;
81 | }
82 |
83 | if (!this.lastBlockNum) {
84 | this.lastBlockNum = res.number - 1;
85 | }
86 |
87 | global.monitor.setBlockTime();
88 |
89 | let start = this.lastBlockNum + 1;
90 | let end = res.number;
91 | this.lastBlockNum = end;
92 |
93 | for (let i = start; i <= end; i++) {
94 | if (callback) callback(i);
95 |
96 | }
97 | })
98 | }
99 |
100 | getPastLogs(blockNumber, nodeConfig, eventList) {
101 | let options = {
102 | fromBlock: blockNumber,
103 | toBlock: blockNumber
104 | };
105 |
106 | return new Promise((resolve, reject) => {
107 | try {
108 | if(!nodeConfig || !nodeConfig.contract || !eventList) reject();
109 |
110 | nodeConfig.web3.eth.getPastLogs(options, (err, logs) => {
111 | if (err) return reject(err);
112 | if (logs.length === 0) resolve();
113 |
114 | for(let subscriber of this.subscribers){
115 | if(!subscriber.node || !subscriber.node.contract || !subscriber.eventList) continue;
116 |
117 | this.parseLogs(subscriber.node.contract, [...logs], subscriber.eventList);
118 | }
119 |
120 | resolve(this.parseLogs(nodeConfig.contract, [...logs], eventList));
121 | }).catch(e => {
122 | reject(e)
123 | });
124 | } catch (e) {
125 | reject(e)
126 | }
127 | });
128 | }
129 |
130 | parseLogs(contract, logs, eventList) {
131 | let receipts = [];
132 | for(let log of logs){
133 | if(log.address.toLowerCase() !== contract._address.toLowerCase()) continue;
134 |
135 | let receipt = contract._decodeEventABI.bind({
136 | name: "ALLEVENTS",
137 | jsonInterface: contract._jsonInterface
138 | })(log);
139 | receipts.push(receipt);
140 | }
141 |
142 | for(let receipt of receipts){
143 | let target = eventList.find(e => e.name === receipt.event);
144 | if(!target) continue;
145 |
146 | target.callback(receipt);
147 | }
148 |
149 | return receipts;
150 | }
151 |
152 | receiveSwapRelay(event) {
153 | if(event.returnValues.bytes32s[0].toLowerCase() !== this.govInfo.id.toLowerCase()) return;
154 | if(event.address.toLowerCase() !== this.orbitHub.address.toLowerCase()) return;
155 |
156 | let returnValues = {
157 | block: event.blockNumber,
158 | fromChain: event.returnValues.fromChain,
159 | bytes32s: event.returnValues.bytes32s,
160 | uints: event.returnValues.uints
161 | };
162 |
163 | const hash = Britto.sha256sol(packer.packRelayedData({
164 | fromChain: returnValues.fromChain,
165 | bytes32s: returnValues.bytes32s,
166 | uints: event.returnValues.uints.slice(2)
167 | })).toString('hex').add0x();
168 |
169 | let obj = this.hashMap.get(hash);
170 | if(!obj){
171 | this.hashMap.set(hash, { timestamp: parseInt(Date.now() / 1000), count: 1 });
172 | }
173 | else{
174 | obj.count = obj.count + 1;
175 |
176 | if(obj.count > 2){ // applyLimitation + validateSwap
177 | logger.hub.info(`Already relayed. ${hash} : ${obj.count}`);
178 | return;
179 | }
180 | }
181 |
182 | const fromInstance = instances[returnValues.fromChain.toLowerCase()];
183 | if(!fromInstance) {
184 | logger.hub.error(`${returnValues.fromChain} instance is not exist`);
185 | return;
186 | }
187 | fromInstance.validateRelayedData(returnValues);
188 | }
189 |
190 | receiveSwapNFTRelay(event) {
191 | if(event.returnValues.bytes32s[0].toLowerCase() !== this.govInfo.id.toLowerCase()) return;
192 | if(event.address.toLowerCase() !== this.orbitHub.address.toLowerCase()) return;
193 |
194 | let returnValues = {
195 | block: event.blockNumber,
196 | fromChain: event.returnValues.fromChain,
197 | bytes32s: event.returnValues.bytes32s,
198 | uints: event.returnValues.uints
199 | };
200 |
201 | const hash = Britto.sha256sol(packer.packRelayedData({
202 | fromChain: returnValues.fromChain,
203 | bytes32s: returnValues.bytes32s,
204 | uints: event.returnValues.uints.slice(2)
205 | })).toString('hex').add0x();
206 |
207 | if(this.hashMap.has(hash)){
208 | logger.hub.info(`Already relayed. ${hash}`);
209 | return;
210 | }
211 | this.hashMap.set(hash, { timestamp: parseInt(Date.now() / 1000) });
212 |
213 | const fromInstance = instances[returnValues.fromChain.toLowerCase()];
214 | if(!fromInstance) {
215 | logger.hub.error(`${returnValues.fromChain} instance is not exist`);
216 | return;
217 | }
218 | fromInstance.validateRelayedNFTData(returnValues);
219 | }
220 |
221 | flushHashMap() {
222 | setTimeout(this.flushHashMap.bind(this), 1000 * 20);
223 |
224 | const now = parseInt(Date.now() / 1000);
225 | for (let [hash, obj] of this.hashMap.entries()) {
226 | if (obj.timestamp + 30 < now) {
227 | this.hashMap.delete(hash);
228 | }
229 | }
230 | }
231 |
232 | getOrbitHub() {
233 | return this.orbitHub;
234 | }
235 |
236 | getChainIds() {
237 | return this.chainIds;
238 | }
239 |
240 | setChainIds() {
241 | const orbitHub = this.orbitHub;
242 | const chainList = this.chainList;
243 |
244 | for(let chain of chainList){
245 | chain = chain.replace(/-v[1-9]$/, '').toUpperCase();
246 | const chainId = Britto.sha256sol(packer.packChainId({
247 | hubContract: orbitHub.address,
248 | chain: chain
249 | })).toString('hex').add0x();
250 |
251 | this.chainIds[chain] = chainId;
252 | }
253 | }
254 | }
255 |
256 | module.exports = OrbitHub;
257 |
--------------------------------------------------------------------------------
/src/hub/logger.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const winston = require('winston');
4 | const moment = require('moment');
5 | const config = require(ROOT + '/config');
6 |
7 | const tsFormat = function () {
8 | return moment().format('YYYY-MM-DD HH:mm:ss');
9 | }
10 |
11 | //////////////////////////////////////////////////////////////////////////////////////////
12 | const myFormat = winston.format.printf(info => {
13 | return '[HUB] ' + tsFormat() + ' ' + info.message;
14 | });
15 |
16 | // Normal Logger: Winston
17 | let logger = winston.createLogger({
18 | level: config.system.logLevel || 'info',
19 | format: winston.format.combine(
20 | myFormat
21 | ),
22 | transports: [
23 | new(winston.transports.Console)({
24 | colorize: true,
25 | handleExceptions: true,
26 | })
27 | ]
28 | });
29 |
30 | module.exports = logger;
31 |
--------------------------------------------------------------------------------
/src/hub/utils/packer.js:
--------------------------------------------------------------------------------
1 | exports.packRelayedData = function(data) {
2 | let result = [];
3 |
4 | result.push({t: 'string', v: data.fromChain});
5 | result.push({t: 'bytes32[]', v: data.bytes32s});
6 | result.push({t: 'uint[]', v: data.uints});
7 |
8 | return result;
9 | }
10 |
11 | exports.packChainId = function (data) {
12 | let result = [];
13 |
14 | result.push({t: 'address', v: data.hubContract});
15 | result.push({t: 'string', v:data.chain});
16 |
17 | return result;
18 | }
19 |
--------------------------------------------------------------------------------
/src/icon/logger.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const winston = require('winston');
4 | const moment = require('moment');
5 | const config = require(ROOT + '/config');
6 |
7 | const tsFormat = function () {
8 | return moment().format('YYYY-MM-DD HH:mm:ss');
9 | }
10 |
11 | //////////////////////////////////////////////////////////////////////////////////////////
12 | const myFormat = winston.format.printf(info => {
13 | return '[ICON] ' + tsFormat() + ' ' + info.message;
14 | });
15 |
16 | // Normal Logger: Winston
17 | let logger = winston.createLogger({
18 | level: config.system.logLevel || 'info',
19 | format: winston.format.combine(
20 | myFormat
21 | ),
22 | transports: [
23 | new(winston.transports.Console)({
24 | colorize: true,
25 | handleExceptions: true,
26 | })
27 | ]
28 | });
29 |
30 | module.exports = logger;
31 |
--------------------------------------------------------------------------------
/src/icon/utils/icon.api.js:
--------------------------------------------------------------------------------
1 | const request = require('request-promise');
2 | const IconService = require('icon-sdk-js').default;
3 | const { IconAmount, IconConverter, IconBuilder, IconWallet, SignedTransaction } = IconService;
4 | const config = require(ROOT + '/config');
5 |
6 | const info = config.info.icon;
7 | const httpProvider = new IconService.HttpProvider(info.ENDPOINT.api);
8 | const icon = new IconService(httpProvider);
9 | const chainName = 'ICON';
10 |
11 | let contractAddress;
12 | let migAddress;
13 | if(config.governance.chain === "ICON"){
14 | contractAddress = config.governance.address;
15 | migAddress = config.governance.address;
16 | }
17 | else{
18 | contractAddress = info.CONTRACT_ADDRESS.minter;
19 | migAddress = info.CONTRACT_ADDRESS.multisig;
20 | }
21 |
22 | const contract = (new IconService.IconBuilder.CallBuilder()).to(contractAddress);
23 | const mig = (new IconService.IconBuilder.CallBuilder()).to(migAddress);
24 |
25 | module.exports.api = icon;
26 | module.exports.contract = contract;
27 | module.exports.contract.address = contractAddress;
28 | module.exports.mig = mig;
29 | module.exports.mig.address = migAddress;
30 | module.exports.converter = IconConverter;
31 |
32 | module.exports.toHex = (_data) => {
33 | return "0x" + IconConverter.toBigNumber(_data).toString(16);
34 | }
35 |
36 | module.exports.getWalletByPK = async (_pk) => {
37 | return IconWallet.loadPrivateKey(_pk);
38 | }
39 |
40 | module.exports.getAddressByPK = async (_pk) => {
41 | return IconWallet.loadPrivateKey(_pk).getAddress();
42 | }
43 |
44 | module.exports.getLastBlock = async () => {
45 | let block = await icon.getLastBlock().execute().catch(e => {
46 | logger.icon.error("getLastBlock error: " + e.message);
47 | global.monitor.setNodeConnectStatus(chainName, info.ENDPOINT.api, 'disconnected');
48 | });
49 |
50 | if(!block)
51 | return;
52 |
53 | global.monitor.setNodeConnectStatus(chainName, info.ENDPOINT.api, 'connected');
54 |
55 | return block;
56 | }
57 |
58 | module.exports.getBalance = async (addr) => {
59 | let balance = await icon.getBalance(addr).execute().catch(e => {
60 | logger.icon.error("getBalance error: " + e.message);
61 | global.monitor.setNodeConnectStatus(chainName, info.ENDPOINT.api, 'disconnected');
62 | })
63 |
64 | if(!balance)
65 | return;
66 |
67 | global.monitor.setNodeConnectStatus(chainName, info.ENDPOINT.api, 'connected');
68 |
69 | return balance.toNumber();
70 | }
71 |
72 | module.exports.getTokenBalance = async (contractAddr, method, params) => {
73 | let token = (new IconService.IconBuilder.CallBuilder()).to(contractAddr);
74 | let transaction;
75 | try {
76 | transaction = await token.method(method).params(params).build();
77 | }
78 | catch (e) {
79 | logger.icon.error("callTransaction build error: " + e.message);
80 | global.monitor.setNodeConnectStatus(chainName, info.ENDPOINT.api, 'disconnected');
81 | }
82 |
83 | if(!transaction)
84 | return;
85 |
86 | let res = await icon.call(transaction).execute().catch(e => {
87 | logger.icon.error("call error: " + e.message);
88 | global.monitor.setNodeConnectStatus(chainName, info.ENDPOINT.api, 'disconnected');
89 | });
90 |
91 | if(!res)
92 | return;
93 |
94 | global.monitor.setNodeConnectStatus(chainName, info.ENDPOINT.api, 'connected');
95 |
96 | return parseInt(res);
97 | }
98 |
99 | module.exports.getTransactionResult = async (txHash) => {
100 | let receipt = await icon.getTransactionResult(txHash).execute().catch(e => {
101 | logger.icon.error("getTransactionResult error: " + e.message);
102 | global.monitor.setNodeConnectStatus(chainName, info.ENDPOINT.api, 'disconnected');
103 | });
104 |
105 | if(!receipt)
106 | return;
107 |
108 | global.monitor.setNodeConnectStatus(chainName, info.ENDPOINT.api, 'connected');
109 |
110 | return receipt
111 | }
112 |
113 | module.exports.getStepPrice = async () => {
114 | const governance = (new IconService.IconBuilder.CallBuilder()).to("cx0000000000000000000000000000000000000001");
115 |
116 | let transaction;
117 | try {
118 | transaction = await governance.method("getStepPrice").params({}).build();
119 | }
120 | catch (e) {
121 | logger.icon.error("callTransaction build error: " + e.message);
122 | global.monitor.setNodeConnectStatus(chainName, info.ENDPOINT.api, 'disconnected');
123 | }
124 |
125 | if(!transaction)
126 | return;
127 |
128 | let res = await icon.call(transaction).execute().catch(e => {
129 | logger.icon.error("call error: " + e.message);
130 | global.monitor.setNodeConnectStatus(chainName, info.ENDPOINT.api, 'disconnected');
131 | });
132 |
133 | if(!res)
134 | return;
135 |
136 | global.monitor.setNodeConnectStatus(chainName, info.ENDPOINT.api, 'connected');
137 |
138 | return res;
139 | }
140 |
141 | module.exports.getCallBuilder = async (address) => {
142 | return (new IconService.IconBuilder.CallBuilder()).to(address);
143 | }
144 |
145 | module.exports.call = async (contract, method, params) => {
146 | let transaction;
147 | try {
148 | transaction = await contract.method(method).params(params).build();
149 | }
150 | catch (e) {
151 | logger.icon.error("callTransaction build error: " + e.message);
152 | global.monitor.setNodeConnectStatus(chainName, info.ENDPOINT.api, 'disconnected');
153 | }
154 |
155 | if(!transaction)
156 | return;
157 |
158 | let res = await icon.call(transaction).execute().catch(e => {
159 | logger.icon.error("call error: " + e.message);
160 | global.monitor.setNodeConnectStatus(chainName, info.ENDPOINT.api, 'disconnected');
161 | });
162 |
163 | if(!res)
164 | return;
165 |
166 | global.monitor.setNodeConnectStatus(chainName, info.ENDPOINT.api, 'connected');
167 |
168 | return res;
169 | }
170 |
171 | module.exports.makeTransferTransaction = async (_from, _to, _value) => {
172 | const { IcxTransactionBuilder } = IconBuilder;
173 |
174 | const from = _from;
175 | const to = _to;
176 | const value = IconAmount.of(_value, IconAmount.Unit.ICX).toLoop();
177 |
178 | const version = IconConverter.toBigNumber(info.ENDPOINT.version);
179 | const nid = IconConverter.toBigNumber(info.ENDPOINT.nid);
180 | const timestamp = (new Date()).getTime() * 1000;
181 |
182 | const builder = new IcxTransactionBuilder();
183 | const transaction = builder
184 | .from(from)
185 | .to(to)
186 | .value(value)
187 | .nid(nid)
188 | .version(version)
189 | .timestamp(timestamp)
190 | .build()
191 |
192 | return transaction;
193 | }
194 |
195 | module.exports.makeContractTransaction = async (_from, _to, _value, _method, _params) => {
196 | const { CallTransactionBuilder } = IconBuilder;
197 |
198 | const from = _from;
199 | const to = _to;
200 | const method = _method;
201 | const params = _params;
202 | const value = IconAmount.of(_value, IconAmount.Unit.ICX).toLoop();
203 |
204 | const version = IconConverter.toBigNumber(info.ENDPOINT.version);
205 | const nid = IconConverter.toBigNumber(info.ENDPOINT.nid);
206 | const timestamp = (new Date()).getTime() * 1000;
207 |
208 | const builder = new CallTransactionBuilder();
209 | const transaction = builder
210 | .from(from)
211 | .to(to)
212 | .value(value)
213 | .nid(nid)
214 | .version(version)
215 | .timestamp(timestamp)
216 | .method(method)
217 | .params(params)
218 | .build()
219 |
220 | return transaction;
221 | }
222 |
223 | module.exports.sendTransaction = async (_wallet, _transaction, _stepLimit) => {
224 | _transaction.stepLimit = parseInt(_stepLimit);
225 |
226 | let signedTransaction = new SignedTransaction(_transaction, _wallet);
227 | let txHash = await icon.sendTransaction(signedTransaction).execute();
228 |
229 | return txHash;
230 | }
231 |
232 | module.exports.estimateStepLimit = async (_transaction) => {
233 | let transaction = makeRPCTransaction(_transaction);
234 | return request.post({
235 | headers: {'Content-Type': 'application/json'},
236 | url: info.ENDPOINT.debug,
237 | body: {
238 | "jsonrpc": "2.0",
239 | "id": 1234,
240 | "method": "debug_estimateStep",
241 | "params": transaction
242 | },
243 | json: true
244 | })
245 | .then(body => {
246 | return body.result;
247 | });
248 | }
249 |
250 | function makeRPCTransaction(_transaction) {
251 | _transaction.version = "0x" + _transaction.version.toString(16);
252 | _transaction.nid = "0x" + _transaction.nid.toString(16);
253 | _transaction.value = "0x" + _transaction.value.toString(16);
254 | _transaction.timestamp = "0x" + (parseInt(_transaction.timestamp)).toString(16);
255 | return json_view(_transaction);
256 | }
257 |
258 | function json_view(j){
259 | return JSON.parse(JSON.stringify(j));
260 | }
261 |
--------------------------------------------------------------------------------
/src/icon/utils/packer.js:
--------------------------------------------------------------------------------
1 | exports.packSwapData = function(data) {
2 | let result = [];
3 |
4 | result.push({t: 'address', v: data.hubContract});
5 | result.push({t: 'string', v: data.fromChain});
6 | result.push({t: 'string', v: data.toChain});
7 | result.push({t: 'bytes', v: toHexBuffer(data.fromAddr)});
8 | result.push({t: 'bytes', v: toHexBuffer(data.toAddr)});
9 | result.push({t: 'bytes', v: toHexBuffer(data.token)});
10 | result.push({t: 'bytes32[]', v: data.bytes32s});
11 | result.push({t: 'uint[]', v: data.uints});
12 | result.push({t: 'bytes', v: toHexBuffer(data.data)});
13 |
14 | return result;
15 | };
16 |
17 | exports.packLimitationData = function(data) {
18 | let result = [];
19 |
20 | result.push({t: 'string', v: "GateKeeper"});
21 | result.push({t: 'string', v: data.fromChain});
22 | result.push({t: 'string', v: data.toChain});
23 | result.push({t: 'bytes', v: toHexBuffer(data.token)});
24 | result.push({t: 'bytes32[]', v: data.bytes32s});
25 | result.push({t: 'uint[]', v: data.uints});
26 |
27 | return result;
28 | }
29 |
30 | function toHexBuffer(str) {
31 | return Buffer.from(str.replace('0x', ""), 'hex');
32 | }
33 |
--------------------------------------------------------------------------------
/src/monitor/index.js:
--------------------------------------------------------------------------------
1 | const { VALIDATOR_MONITOR } = require(`${ROOT}/config/${process.env.PROFILE}/endpoints.js`);
2 | const request = require('request');
3 |
4 | function ozysReport(url, body) {
5 | return new Promise((resolve, reject) => {
6 | const options = {
7 | method: 'POST',
8 | json: true,
9 | body,
10 | }
11 | request(url, options, (err, res) => {
12 | if (err) {
13 | return reject(err);
14 | }
15 | resolve(res.body);
16 | })
17 | });
18 | }
19 |
20 | class Monitor {
21 | constructor () {
22 | this.validatorAddress;
23 | this.publicKey;
24 | this.chain;
25 | this.address = {};
26 | this.nodeConnect = {};
27 | this.blockNumber = {};
28 | this.ibc = {};
29 |
30 | this.lastBlockTime = parseInt(Date.now() / 1000);
31 | this.connectionHandler();
32 |
33 | if(!VALIDATOR_MONITOR){
34 | console.log("Validator Monitor set is empty!");
35 | return;
36 | }
37 |
38 | for (const [key, value] of Object.entries(VALIDATOR_MONITOR) ) {
39 | setInterval(() => {
40 | this.reportMonitorStatus(key, value);
41 | }, 600 * 1000);
42 | }
43 | }
44 |
45 | connectionHandler() {
46 | setTimeout(this.connectionHandler.bind(this), 1000 * 60);
47 |
48 | const now = parseInt(Date.now() / 1000);
49 | if(this.lastBlockTime + 60 * 10 < now) process.exit(1);
50 | }
51 |
52 | static getChainFullName(chain) {
53 | chain = chain.toUpperCase();
54 |
55 | if(chain.substr(0, 2) === 'GOV' && chain !== 'GOV_OCHAIN')
56 | return null;
57 |
58 | let fullNames = {
59 | ETH: 'ethereum',
60 | ETH_V1: 'ethereum-v1',
61 | ETH_V2: 'ethereum-v2',
62 | ETH_MAINNET: 'ethereum_mainnet',
63 | KLAYTN: 'klaytn',
64 | KLAYTN_V1: 'klaytn-v1',
65 | KLAYTN_V2: 'klaytn-v2',
66 | KLAYTN_MAINNET: 'klaytn_mainnet',
67 | ICON: 'icon',
68 | ICON_V1: 'icon-v1',
69 | ICON_V2: 'icon-v2',
70 | ICON_MAINNET: 'icon_mainnet',
71 | XRP: 'xrp',
72 | BSC: 'bsc',
73 | HECO: 'heco',
74 | MATIC: 'matic',
75 | CELO: 'celo',
76 | STACKS_LAYER_1: 'stacks_layer_1',
77 | TON_LAYER_1: 'ton_layer_1'
78 | };
79 |
80 | return fullNames[chain] || (chain && chain.toLowerCase()) || "";
81 | }
82 |
83 | reportMonitorStatus(method, data) {
84 | try {
85 | switch (method) {
86 | case "ozys":
87 | ozysReport(data.monitor, this.json());
88 | break;
89 | default:
90 | console.log(`unknown monitor method offered: ${method}`);
91 | break;
92 | }
93 | } catch (e) {}
94 | }
95 |
96 | setNodeConnectStatus (chain, address, connectionStatus) {
97 | if (!chain || !address) {
98 | return;
99 | }
100 |
101 | chain = Monitor.getChainFullName(chain);
102 | if (!chain) {
103 | return;
104 | }
105 |
106 | this.nodeConnect[chain] = this.nodeConnect[chain] || {};
107 | this.nodeConnect[chain].status = connectionStatus;
108 | }
109 |
110 | setNodeElectionStatus (chain, address, electedBlock) {
111 | if (!chain || !address) {
112 | return;
113 | }
114 |
115 | chain = Monitor.getChainFullName(chain);
116 | if (!chain) {
117 | return;
118 | }
119 |
120 | this.nodeConnect[chain] = this.nodeConnect[chain] || {};
121 | this.nodeConnect[chain].electedBlock = electedBlock;
122 | }
123 |
124 | setBlockNumber (chain, block) {
125 | if (!chain || !block)
126 | return;
127 |
128 | chain = Monitor.getChainFullName(chain);
129 | if(!chain)
130 | return;
131 |
132 | if (!this.blockNumber[chain])
133 | this.blockNumber[chain] = {}
134 |
135 | this.blockNumber[chain] = block
136 | }
137 |
138 | setBlockTime() {
139 | this.lastBlockTime = parseInt(Date.now() / 1000);
140 | }
141 |
142 | setProgress(chain, func, block) {
143 | if (!chain || !func || !block)
144 | return;
145 |
146 | chain = Monitor.getChainFullName(chain);
147 | if(!chain)
148 | return;
149 |
150 | if (!this.ibc[chain])
151 | this.ibc[chain] = {}
152 |
153 | this.ibc[chain][func] = block
154 | }
155 |
156 | json () {
157 | return {
158 | version: VERSION,
159 | validatorAddress: this.validatorAddress,
160 | publicKey: this.publicKey,
161 | chain: this.chain,
162 | address: this.address,
163 | nodeConnection: this.nodeConnect,
164 | lastBlockTime: this.lastBlockTime,
165 | }
166 | }
167 | }
168 |
169 | module.exports = Monitor;
170 |
--------------------------------------------------------------------------------
/src/stacks/logger.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const winston = require('winston');
4 | const moment = require('moment');
5 | const config = require(ROOT + '/config');
6 |
7 | const tsFormat = function () {
8 | return moment().format('YYYY-MM-DD HH:mm:ss');
9 | }
10 |
11 | //////////////////////////////////////////////////////////////////////////////////////////
12 | const myFormat = winston.format.printf(info => {
13 | return '[STACKS] ' + tsFormat() + ' ' + info.message;
14 | });
15 |
16 | // Normal Logger: Winston
17 | let logger = winston.createLogger({
18 | level: config.system.logLevel || 'info',
19 | format: winston.format.combine(
20 | myFormat
21 | ),
22 | transports: [
23 | new(winston.transports.Console)({
24 | colorize: true,
25 | handleExceptions: true,
26 | })
27 | ]
28 | });
29 |
30 | module.exports = logger;
31 |
--------------------------------------------------------------------------------
/src/stacks/utils/packer.js:
--------------------------------------------------------------------------------
1 | exports.packSwapData = function(data) {
2 | let result = [];
3 |
4 | result.push({t: 'address', v: data.hubContract});
5 | result.push({t: 'string', v: data.fromChain});
6 | result.push({t: 'string', v: data.toChain});
7 | result.push({t: 'bytes', v: toHexBuffer(data.fromAddr)});
8 | result.push({t: 'bytes', v: toHexBuffer(data.token)});
9 | result.push({t: 'bytes32', v: data.bytes32s[0]});
10 | result.push({t: 'bytes32', v: data.bytes32s[1]});
11 | result.push({t: 'uint', v: data.uints[1]});
12 | result.push({t: 'uint', v: data.uints[2]});
13 | result.push({t: 'uint', v: data.uints[3]});
14 |
15 | return result;
16 | };
17 |
18 | exports.packDataHash = function(data) {
19 | let result = [];
20 |
21 | result.push({t: 'address', v: data.hubContract});
22 | result.push({t: 'string', v: data.fromChain});
23 | result.push({t: 'string', v: data.toChain});
24 | result.push({t: 'bytes', v: toHexBuffer(data.fromAddr)});
25 | result.push({t: 'bytes', v: toHexBuffer(data.token)});
26 | result.push({t: 'bytes32', v: data.bytes32s[0]});
27 | result.push({t: 'bytes32', v: data.bytes32s[1]});
28 | result.push({t: 'uint', v: data.uints[1]});
29 | result.push({t: 'uint', v: data.uints[2]});
30 |
31 | return result;
32 | }
33 |
34 | exports.packLimitationData = function(data) {
35 | let result = [];
36 |
37 | result.push({t: 'string', v: "GateKeeper"});
38 | result.push({t: 'string', v: data.fromChain});
39 | result.push({t: 'string', v: data.toChain});
40 | result.push({t: 'bytes', v: toHexBuffer(data.token)});
41 | result.push({t: 'bytes32[]', v: data.bytes32s});
42 | result.push({t: 'uint[]', v: data.uints});
43 |
44 | return result;
45 | }
46 |
47 | function toHexBuffer(str) {
48 | return Buffer.from(str.replace('0x', ""), 'hex');
49 | }
50 |
--------------------------------------------------------------------------------
/src/stacks/utils/stacks.bridgeutils.js:
--------------------------------------------------------------------------------
1 | const request = require("request-promise");
2 | const config = require(ROOT + '/config');
3 | const Endpoints = config.endpoints;
4 | const BridgeUtils = require(ROOT + '/lib/bridgeutils');
5 |
6 | const {
7 | AddressVersion,
8 | AnchorMode,
9 | BufferReader,
10 | deserializeMemoString,
11 | TransactionVersion,
12 | addressFromVersionHash,
13 | addressToString,
14 | broadcastTransaction,
15 | callReadOnlyFunction,
16 | deserializeCV,
17 | makeUnsignedSTXTokenTransfer,
18 | nextVerification,
19 | TransactionSigner,
20 | makeSigHashPreSign,
21 | } = require("@stacks/transactions");
22 |
23 | const {
24 | StacksTestnet,
25 | StacksMainnet,
26 | } = require("@stacks/network");
27 |
28 | const baseReqObj = {
29 | headers: {'Content-Type': 'application/json', 'User-Agent': 'OrbitBridge-Request'},
30 | json: true,
31 | };
32 |
33 | class StacksBridgeUtils extends BridgeUtils {
34 | constructor() {
35 | super();
36 |
37 | let addressVersion = AddressVersion.MainnetMultiSig;
38 | let singleAddressVersion = AddressVersion.MainnetSingleSig;
39 | let transactionVersion = TransactionVersion.Mainnet;
40 | let network = new StacksMainnet();
41 | if (Endpoints.stacks.network === "testnet") {
42 | addressVersion = AddressVersion.TestnetMultiSig;
43 | singleAddressVersion = AddressVersion.TestnetSingleSig;
44 | transactionVersion = TransactionVersion.Testnet;
45 | network = new StacksTestnet();
46 | }
47 |
48 | this.AddressVersion = addressVersion;
49 | this.SingleAddressVersion = singleAddressVersion;
50 | this.TransactionVersion = transactionVersion;
51 | this.Network = network;
52 |
53 | let endpoints = Endpoints.stacks;
54 | global.monitor.setNodeConnectStatus("stacks", `${endpoints.url}/${endpoints.network ? endpoints.network : "mainnet"}`, "connected");
55 | }
56 |
57 | hexToCV(hex) {
58 | if (hex.startsWith('0x'))
59 | hex = hex.substring(2);
60 | return deserializeCV(new BufferReader(Buffer.from(hex, 'hex')))
61 | }
62 |
63 | async getLatestBlock() {
64 | const response = await request.get({
65 | url: `${Endpoints.stacks.url}/extended/v1/block?limit=1`,
66 | ...baseReqObj,
67 | }).catch(e => {
68 | logger.stacks.error(`getTransaction error. tx:${thash}, err:${e.message}`);
69 | });
70 | if (!response) {
71 | return;
72 | }
73 |
74 | return response.results[0];
75 | }
76 |
77 | async getTransaction(thash) {
78 | const tx = await request.get({
79 | url: `${Endpoints.stacks.url}/extended/v1/tx/${thash}`,
80 | ...baseReqObj,
81 | }).catch(e => {
82 | logger.stacks.error(`getTransaction error. tx:${thash}, err:${e.message}`);
83 | });
84 | if (!tx) {
85 | return;
86 | }
87 | if (tx.token_transfer && tx.token_transfer.memo) {
88 | let memo = tx.token_transfer.memo.replace("0x", "");
89 | memo = deserializeMemoString(new BufferReader(Buffer.from(memo, "hex")));
90 | memo.content = memo.content.replace(/\u0000/g, "");
91 | tx.token_transfer.memo = memo;
92 | }
93 | return tx;
94 | };
95 |
96 | async getBalance(address) {
97 | const stx = await request.get({
98 | url: `${Endpoints.stacks.url}/extended/v1/address/${address}/stx`,
99 | ...baseReqObj,
100 | }).catch(e => {
101 | logger.stacks.error(`getBalance error. addr:${address}, err:${e.message}`);
102 | });
103 | if(!stx)
104 | return;
105 |
106 | return stx.balance;
107 | };
108 |
109 | async getNonce(address) {
110 | const account = await request.get({
111 | url: `${Endpoints.stacks.url}/extended/v1/address/${address}/nonces`,
112 | ...baseReqObj,
113 | }).catch(e => {
114 | logger.stacks.error(`getNonce error. addr:${address}, err:${e.message}`);
115 | });
116 | if(!account)
117 | return;
118 |
119 | return account.possible_next_nonce;
120 | }
121 |
122 | async makeUnsignedSTXTokenTransfer(nonce, publicKeys, quorumCount, toAddr, memo, amount) {
123 | publicKeys = publicKeys.map(key => { return key.replace("0x",""); });
124 | const transaction = await makeUnsignedSTXTokenTransfer({
125 | recipient : toAddr,
126 | nonce: nonce,
127 | amount: amount,
128 | memo: memo,
129 | numSignatures: parseInt(quorumCount), // number of signature required
130 | publicKeys: publicKeys, // public key string array with >= numSignatures elements
131 | network: this.Network,
132 | anchorMode: AnchorMode.Any,
133 | }).catch(e => {
134 | logger.stacks.error(`makeTransaction error. nonce: ${nonce}, err:${e.message}`);
135 | });
136 | if(!transaction)
137 | return;
138 |
139 | return transaction;
140 | }
141 |
142 | async readContract(contractAddress, contractName, functionName, functionArgs, sender) {
143 | const ret = await callReadOnlyFunction({
144 | contractAddress,
145 | contractName,
146 | functionName,
147 | functionArgs,
148 | network: this.Network,
149 | senderAddress: sender,
150 | });
151 | if (!ret) {
152 | return;
153 | }
154 |
155 | return ret;
156 | }
157 |
158 | async estimateFee(serializedTx) {
159 | const stx = await request.post({
160 | url: `${Endpoints.stacks.url}/extended/v1/fee_rate`,
161 | ...baseReqObj,
162 | params: {transaction : serializedTx}
163 | }).catch(e => {
164 | logger.stacks.error(`estimateFee error. tx:${serializedTx}, err:${e.message}`);
165 | });
166 | if(!stx)
167 | return;
168 |
169 | return stx.fee_rate;
170 | }
171 |
172 | getMultiAddressFromHex(hexAddr) {
173 | return addressToString(addressFromVersionHash(this.AddressVersion, hexAddr.replace("0x", "")));
174 | }
175 |
176 | getSingleAddressFromHex(hexAddr) {
177 | return addressToString(addressFromVersionHash(this.SingleAddressVersion, hexAddr.replace("0x", "")));
178 | }
179 |
180 | async broadcastTransaction(transaction) {
181 | const res = await broadcastTransaction(transaction.serialize(), Endpoints.stacks.url).catch(e => {
182 | logger.stacks.error(`broadcastTransaction fail. err: ${e.message}`);
183 | });
184 | if(!res)
185 | return;
186 |
187 | return res.txid;
188 | }
189 |
190 | getMemo(data) {
191 | if (!data) {
192 | return "";
193 | }
194 | return Buffer.from(data.replace("0x",""), 'hex').toString('utf-8');
195 | }
196 |
197 | getCurrentSigHash(lastSigHash, lastSignature, fee, nonce){
198 | let res;
199 | try{
200 | res = nextVerification(
201 | lastSigHash.replace("0x",""),
202 | 4, // Standard
203 | fee,
204 | nonce,
205 | 1, // Uncompressed
206 | {data: lastSignature.replace("0x","")} // {00,01}{r}{s}
207 | )
208 | } catch(e) {
209 | logger.stacks.error(`getCrrentSigHash fail. err: ${e.message}`);
210 | return;
211 | };
212 | if(!res)
213 | return;
214 |
215 | return res.nextSigHash;
216 | }
217 |
218 | async getInitialSigHash(transaction){
219 | transaction.auth.spendingCondition.fields = [];
220 | const signer = new TransactionSigner(transaction);
221 | if(!signer || !signer.sigHash)
222 | return;
223 |
224 | return signer.sigHash;
225 | }
226 |
227 | async getSigHashPreSign(curSigHash, authType, fee, nonce){
228 | let res;
229 | try{
230 | res = makeSigHashPreSign(curSigHash, authType, fee, nonce);
231 | } catch(e) {
232 | logger.stacks.error(`makeSigHashPreSign fail. err: ${e.message}`);
233 | return;
234 | }
235 | if(!res)
236 | return;
237 |
238 | return res;
239 | }
240 | }
241 |
242 | module.exports = StacksBridgeUtils;
243 |
--------------------------------------------------------------------------------
/src/stacks_layer_1/logger.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const winston = require('winston');
4 | const moment = require('moment');
5 | const config = require(ROOT + '/config');
6 |
7 | const tsFormat = function () {
8 | return moment().format('YYYY-MM-DD HH:mm:ss');
9 | }
10 |
11 | //////////////////////////////////////////////////////////////////////////////////////////
12 | const myFormat = winston.format.printf(info => {
13 | return '[STACKS_LAYER_1] ' + tsFormat() + ' ' + info.message;
14 | });
15 |
16 | // Normal Logger: Winston
17 | let logger = winston.createLogger({
18 | level: config.system.logLevel || 'info',
19 | format: winston.format.combine(
20 | myFormat
21 | ),
22 | transports: [
23 | new(winston.transports.Console)({
24 | colorize: true,
25 | handleExceptions: true,
26 | })
27 | ]
28 | });
29 |
30 | module.exports = logger;
31 |
--------------------------------------------------------------------------------
/src/stacks_layer_1/utils/packer.js:
--------------------------------------------------------------------------------
1 | exports.packSwapData = function(data) {
2 | let result = [];
3 |
4 | result.push({t: 'address', v: data.hubContract});
5 | result.push({t: 'string', v: data.fromChain});
6 | result.push({t: 'string', v: data.toChain});
7 | result.push({t: 'bytes', v: toHexBuffer(data.fromAddr)});
8 | result.push({t: 'bytes', v: toHexBuffer(data.toAddr)});
9 | result.push({t: 'bytes', v: toHexBuffer(data.token)});
10 | result.push({t: 'bytes32[]', v: data.bytes32s});
11 | result.push({t: 'uint[]', v: data.uints});
12 | result.push({t: 'bytes', v: toHexBuffer(data.data)});
13 |
14 | return result;
15 | };
16 |
17 | exports.packSuggestHash = function(data) {
18 | let result = [];
19 |
20 | result.push({t: 'address', v: data.contract});
21 | result.push({t: 'bytes32', v: data.govId});
22 | result.push({t: 'uint', v: data.suggestIndex.toString()});
23 | result.push({t: 'uint', v: data.swapIndex.toString()});
24 | result.push({t: 'uint', v: data.fee.toString()});
25 | result.push({t: 'uint', v: data.seq.toString()});
26 |
27 | return result;
28 | };
29 |
30 | exports.packSigningHash = function(data) {
31 | let result = [];
32 |
33 | result.push({t: 'address', v: data.contract});
34 | result.push({t: 'bytes32', v: data.govId});
35 | result.push({t: 'uint', v: data.selectionIndex});
36 | result.push({t: 'address[]', v: data.vaList});
37 |
38 | return result;
39 | };
40 |
41 | exports.packStacksTagHash = function(data) {
42 | let result = [];
43 |
44 | result.push({t: 'string', v: data.toChain});
45 | result.push({t: 'bytes', v: toHexBuffer(data.toAddress)});
46 | result.push({t: 'bytes', v: toHexBuffer(data.transfortData)});
47 |
48 | return result;
49 | }
50 |
51 | exports.packLimitationData = function(data) {
52 | let result = [];
53 |
54 | result.push({t: 'string', v: "GateKeeper"});
55 | result.push({t: 'string', v: data.fromChain});
56 | result.push({t: 'string', v: data.toChain});
57 | result.push({t: 'bytes', v: toHexBuffer(data.token)});
58 | result.push({t: 'bytes32[]', v: data.bytes32s});
59 | result.push({t: 'uint[]', v: data.uints});
60 |
61 | return result;
62 | }
63 |
64 | function toHexBuffer(str) {
65 | return Buffer.from(str.replace('0x', ""), 'hex');
66 | }
67 |
--------------------------------------------------------------------------------
/src/stacks_layer_1/utils/stacks.bridgeutils.js:
--------------------------------------------------------------------------------
1 | const request = require("request-promise");
2 | const config = require(ROOT + '/config');
3 | const Endpoints = config.endpoints;
4 | const BridgeUtils = require(ROOT + '/lib/bridgeutils');
5 |
6 | const {
7 | AddressVersion,
8 | AnchorMode,
9 | BufferReader,
10 | deserializeMemoString,
11 | TransactionVersion,
12 | addressFromVersionHash,
13 | addressToString,
14 | broadcastTransaction,
15 | makeUnsignedSTXTokenTransfer,
16 | nextVerification,
17 | TransactionSigner,
18 | makeSigHashPreSign,
19 | } = require("@stacks/transactions");
20 |
21 | const {
22 | StacksTestnet,
23 | StacksMainnet,
24 | } = require("@stacks/network");
25 |
26 | const baseReqObj = {
27 | headers: {'Content-Type': 'application/json', 'User-Agent': 'OrbitBridge-Request'},
28 | json: true,
29 | };
30 |
31 | class StacksBridgeUtils extends BridgeUtils {
32 | constructor() {
33 | super();
34 |
35 | let addressVersion = AddressVersion.MainnetMultiSig;
36 | let singleAddressVersion = AddressVersion.MainnetSingleSig;
37 | let transactionVersion = TransactionVersion.Mainnet;
38 | let network = new StacksMainnet();
39 | if (Endpoints.stacks.network === "testnet") {
40 | addressVersion = AddressVersion.TestnetMultiSig;
41 | singleAddressVersion = AddressVersion.TestnetSingleSig;
42 | transactionVersion = TransactionVersion.Testnet;
43 | network = new StacksTestnet();
44 | }
45 |
46 | this.AddressVersion = addressVersion;
47 | this.SingleAddressVersion = singleAddressVersion;
48 | this.TransactionVersion = transactionVersion;
49 | this.Network = network;
50 |
51 | let endpoints = Endpoints.stacks;
52 | global.monitor.setNodeConnectStatus("stacks", `${endpoints.url}/${endpoints.network ? endpoints.network : "mainnet"}`, "connected");
53 | }
54 |
55 | async getTransaction(thash) {
56 | const tx = await request.get({
57 | url: `${Endpoints.stacks.url}/extended/v1/tx/${thash}`,
58 | ...baseReqObj,
59 | }).catch(e => {
60 | logger.stacks_layer_1.error(`getTransaction error. tx:${thash}, err:${e.message}`);
61 | });
62 | if (!tx) {
63 | return;
64 | }
65 | if (tx.token_transfer && tx.token_transfer.memo) {
66 | let memo = tx.token_transfer.memo.replace("0x", "");
67 | memo = deserializeMemoString(new BufferReader(Buffer.from(memo, "hex")));
68 | memo.content = memo.content.replace(/\u0000/g, "");
69 | tx.token_transfer.memo = memo;
70 | }
71 | return tx;
72 | };
73 |
74 | async getBalance(address) {
75 | const stx = await request.get({
76 | url: `${Endpoints.stacks.url}/extended/v1/address/${address}/stx`,
77 | ...baseReqObj,
78 | }).catch(e => {
79 | logger.stacks_layer_1.error(`getBalance error. addr:${address}, err:${e.message}`);
80 | });
81 | if(!stx)
82 | return;
83 |
84 | return stx.balance;
85 | };
86 |
87 | async getNonce(address) {
88 | const account = await request.get({
89 | url: `${Endpoints.stacks.url}/extended/v1/address/${address}/nonces`,
90 | ...baseReqObj,
91 | }).catch(e => {
92 | logger.stacks_layer_1.error(`getNonce error. addr:${address}, err:${e.message}`);
93 | });
94 | if(!account)
95 | return;
96 |
97 | return account.possible_next_nonce;
98 | }
99 |
100 | async getCurrentBlock() {
101 | const block = await request.get({
102 | url: `${Endpoints.stacks.url}/extended/v1/block`,
103 | ...baseReqObj,
104 | }).catch(e => {
105 | logger.stacks_layer_1.error(`getCurrentBlock error.`);
106 | });
107 | if(!block)
108 | return;
109 |
110 | return block.results[0].height;
111 | }
112 |
113 | async makeUnsignedSTXTokenTransfer(nonce, publicKeys, quorumCount, toAddr, memo, amount) {
114 | publicKeys = publicKeys.map(key => { return key.replace("0x",""); });
115 | const transaction = await makeUnsignedSTXTokenTransfer({
116 | recipient : toAddr,
117 | nonce: nonce,
118 | amount: amount,
119 | memo: memo,
120 | numSignatures: parseInt(quorumCount), // number of signature required
121 | publicKeys: publicKeys, // public key string array with >= numSignatures elements
122 | network: this.Network,
123 | anchorMode: AnchorMode.Any,
124 | }).catch(e => {
125 | logger.stacks_layer_1.error(`makeTransaction error. nonce: ${nonce}, err:${e.message}`);
126 | });
127 | if(!transaction)
128 | return;
129 |
130 | return transaction;
131 | }
132 |
133 | async estimateFee(serializedTx) {
134 | const stx = await request.post({
135 | url: `${Endpoints.stacks.url}/extended/v1/fee_rate`,
136 | ...baseReqObj,
137 | params: {transaction : serializedTx}
138 | }).catch(e => {
139 | logger.stacks_layer_1.error(`estimateFee error. tx:${serializedTx}, err:${e.message}`);
140 | });
141 | if(!stx)
142 | return;
143 |
144 | return stx.fee_rate;
145 | }
146 |
147 | getMultiAddressFromHex(hexAddr) {
148 | return addressToString(addressFromVersionHash(this.AddressVersion, hexAddr.replace("0x", "")));
149 | }
150 |
151 | getSingleAddressFromHex(hexAddr) {
152 | return addressToString(addressFromVersionHash(this.SingleAddressVersion, hexAddr.replace("0x", "")));
153 | }
154 |
155 | async broadcastTransaction(transaction) {
156 | const res = await broadcastTransaction(transaction.serialize(), Endpoints.stacks.url).catch(e => {
157 | logger.stacks_layer_1.error(`broadcastTransaction fail. err: ${e.message}`);
158 | });
159 | if(!res)
160 | return;
161 |
162 | return res.txid;
163 | }
164 |
165 | getMemo(data) {
166 | if (!data) {
167 | return "";
168 | }
169 | return Buffer.from(data.replace("0x",""), 'hex').toString('utf-8');
170 | }
171 |
172 | getCurrentSigHash(lastSigHash, lastSignature, fee, nonce){
173 | let res;
174 | try{
175 | res = nextVerification(
176 | lastSigHash.replace("0x",""),
177 | 4, // Standard
178 | fee,
179 | nonce,
180 | 1, // Uncompressed
181 | {data: lastSignature.replace("0x","")} // {00,01}{r}{s}
182 | )
183 | } catch(e) {
184 | logger.stacks_layer_1.error(`getCrrentSigHash fail. err: ${e.message}`);
185 | return;
186 | };
187 | if(!res)
188 | return;
189 |
190 | return res.nextSigHash;
191 | }
192 |
193 | async getInitialSigHash(transaction){
194 | transaction.auth.spendingCondition.fields = [];
195 | const signer = new TransactionSigner(transaction);
196 | if(!signer || !signer.sigHash)
197 | return;
198 |
199 | return signer.sigHash;
200 | }
201 |
202 | async getSigHashPreSign(curSigHash, authType, fee, nonce){
203 | let res;
204 | try{
205 | res = makeSigHashPreSign(curSigHash, authType, fee, nonce);
206 | } catch(e) {
207 | logger.stacks_layer_1.error(`makeSigHashPreSign fail. err: ${e.message}`);
208 | return;
209 | }
210 | if(!res)
211 | return;
212 |
213 | return res;
214 | }
215 | }
216 |
217 | module.exports = StacksBridgeUtils;
218 |
--------------------------------------------------------------------------------
/src/ton/logger.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const winston = require('winston');
4 | const moment = require('moment');
5 | const config = require(ROOT + '/config');
6 |
7 | const tsFormat = function () {
8 | return moment().format('YYYY-MM-DD HH:mm:ss');
9 | }
10 |
11 | //////////////////////////////////////////////////////////////////////////////////////////
12 | const myFormat = winston.format.printf(info => {
13 | return '[TON] ' + tsFormat() + ' ' + info.message;
14 | });
15 |
16 | // Normal Logger: Winston
17 | let logger = winston.createLogger({
18 | level: config.system.logLevel || 'info',
19 | format: winston.format.combine(
20 | myFormat
21 | ),
22 | transports: [
23 | new(winston.transports.Console)({
24 | colorize: true,
25 | handleExceptions: true,
26 | })
27 | ]
28 | });
29 |
30 | module.exports = logger;
31 |
--------------------------------------------------------------------------------
/src/ton/utils/packer.js:
--------------------------------------------------------------------------------
1 | exports.packSwapDataA = function(data) {
2 | let result = [];
3 |
4 | result.push({t: 'address', v: data.hubContract});
5 | result.push({t: 'bytes32', v: data.fromChainId});
6 | result.push({t: 'bytes32', v: data.toChainId});
7 | result.push({t: 'bytes', v: toHexBuffer(data.fromAddr)});
8 |
9 | return result;
10 | }
11 |
12 | exports.packSwapDataB = function(data) {
13 | let result = [];
14 |
15 | result.push({t: 'bytes', v: toHexBuffer(data.toAddr)});
16 | result.push({t: 'bytes', v: toHexBuffer(data.token)});
17 | result.push({t: 'bytes32[]', v: data.bytes32s});
18 |
19 | return result;
20 | }
21 |
22 | exports.packSwapDataC = function(data) {
23 | let result = [];
24 |
25 | result.push({t: 'uint[]', v: data.uints});
26 |
27 | return result;
28 | }
29 |
30 | exports.packSigHash = function(data) {
31 | let result = [];
32 |
33 | result.push({t: 'bytes32', v: data.hashA});
34 | result.push({t: 'bytes32', v: data.hashB});
35 | result.push({t: 'bytes32', v: data.hashC});
36 |
37 | return result;
38 | }
39 |
40 | exports.packLimitationData = function(data) {
41 | let result = [];
42 |
43 | result.push({t: 'string', v: "GateKeeper"});
44 | result.push({t: 'string', v: data.fromChain});
45 | result.push({t: 'string', v: data.toChain});
46 | result.push({t: 'bytes', v: toHexBuffer(data.token)});
47 | result.push({t: 'bytes32[]', v: data.bytes32s});
48 | result.push({t: 'uint[]', v: data.uints});
49 |
50 | return result;
51 | }
52 |
53 | function toHexBuffer(str) {
54 | return Buffer.from(str.replace('0x', ""), 'hex');
55 | }
56 |
--------------------------------------------------------------------------------
/src/ton_layer_1/logger.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const winston = require('winston');
4 | const moment = require('moment');
5 | const config = require(ROOT + '/config');
6 |
7 | const tsFormat = function () {
8 | return moment().format('YYYY-MM-DD HH:mm:ss');
9 | }
10 |
11 | //////////////////////////////////////////////////////////////////////////////////////////
12 | const myFormat = winston.format.printf(info => {
13 | return '[TON_LAYER_1] ' + tsFormat() + ' ' + info.message;
14 | });
15 |
16 | // Normal Logger: Winston
17 | let logger = winston.createLogger({
18 | level: config.system.logLevel || 'info',
19 | format: winston.format.combine(
20 | myFormat
21 | ),
22 | transports: [
23 | new(winston.transports.Console)({
24 | colorize: true,
25 | handleExceptions: true,
26 | })
27 | ]
28 | });
29 |
30 | module.exports = logger;
31 |
--------------------------------------------------------------------------------
/src/ton_layer_1/utils/packer.js:
--------------------------------------------------------------------------------
1 | exports.packSwapDataA = function(data) {
2 | let result = [];
3 |
4 | result.push({t: 'address', v: data.hubContract});
5 | result.push({t: 'bytes32', v: data.fromChainId});
6 | result.push({t: 'bytes32', v: data.toChainId});
7 | result.push({t: 'bytes', v: toHexBuffer(data.fromAddr)});
8 |
9 | return result;
10 | }
11 |
12 | exports.packSwapDataB = function(data) {
13 | let result = [];
14 |
15 | result.push({t: 'bytes', v: toHexBuffer(data.toAddr)});
16 | result.push({t: 'bytes', v: toHexBuffer(data.token)});
17 | result.push({t: 'bytes32[]', v: data.bytes32s});
18 |
19 | return result;
20 | }
21 |
22 | exports.packSwapDataC = function(data) {
23 | let result = [];
24 |
25 | result.push({t: 'uint[]', v: data.uints});
26 |
27 | return result;
28 | }
29 |
30 | exports.packSwapDataD = function(data) {
31 | let result = [];
32 |
33 | result.push({t: 'bytes', v: toHexBuffer(data.data)});
34 |
35 | return result;
36 | }
37 |
38 | exports.packSigHash = function(data) {
39 | let result = [];
40 |
41 | result.push({t: 'bytes32', v:data.hash1});
42 | result.push({t: 'bytes32', v:data.hash2});
43 |
44 | return result;
45 | }
46 |
47 | exports.packLimitationData = function(data) {
48 | let result = [];
49 |
50 | result.push({t: 'string', v: "GateKeeper"});
51 | result.push({t: 'string', v: data.fromChain});
52 | result.push({t: 'string', v: data.toChain});
53 | result.push({t: 'bytes', v: toHexBuffer(data.token)});
54 | result.push({t: 'bytes32[]', v: data.bytes32s});
55 | result.push({t: 'uint[]', v: data.uints});
56 |
57 | return result;
58 | }
59 |
60 | exports.packTagHash = function(data) {
61 | let result = [];
62 |
63 | result.push({t: 'string', v: 'TON'});
64 | result.push({t: 'string', v: 'AddressBook'});
65 | result.push({t: 'uint256', v: data.version});
66 | result.push({t: 'string', v: data.toChain});
67 | result.push({t: 'bytes', v: toHexBuffer(data.toAddress)});
68 | result.push({t: 'bytes', v: toHexBuffer(data.transfortData)});
69 |
70 | return result;
71 | }
72 |
73 | function toHexBuffer(str) {
74 | return Buffer.from(str.replace('0x', ""), 'hex');
75 | }
76 |
--------------------------------------------------------------------------------
/src/xrp/logger.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const winston = require('winston');
4 | const moment = require('moment');
5 | const config = require(ROOT + '/config');
6 |
7 | const tsFormat = function () {
8 | return moment().format('YYYY-MM-DD HH:mm:ss');
9 | }
10 |
11 | //////////////////////////////////////////////////////////////////////////////////////////
12 | const myFormat = winston.format.printf(info => {
13 | return '[XRP] ' + tsFormat() + ' ' + info.message;
14 | });
15 |
16 | // Normal Logger: Winston
17 | let logger = winston.createLogger({
18 | level: config.system.logLevel || 'info',
19 | format: winston.format.combine(
20 | myFormat
21 | ),
22 | transports: [
23 | new(winston.transports.Console)({
24 | colorize: true,
25 | handleExceptions: true,
26 | })
27 | ]
28 | });
29 |
30 | module.exports = logger;
--------------------------------------------------------------------------------
/src/xrp/utils/packer.js:
--------------------------------------------------------------------------------
1 | exports.packSwapData = function(data) {
2 | let result = [];
3 |
4 | result.push({t: 'address', v: data.hubContract});
5 | result.push({t: 'string', v: data.fromChain});
6 | result.push({t: 'string', v: data.toChain});
7 | result.push({t: 'bytes', v: toHexBuffer(data.fromAddr)});
8 | result.push({t: 'bytes', v: toHexBuffer(data.toAddr)});
9 | result.push({t: 'bytes', v: toHexBuffer(data.token)});
10 | result.push({t: 'bytes32[]', v: data.bytes32s});
11 | result.push({t: 'uint[]', v: data.uints});
12 | result.push({t: 'bytes', v: toHexBuffer(data.data)});
13 |
14 | return result;
15 | };
16 |
17 | exports.packSuggestHash = function(data) {
18 | let result = [];
19 |
20 | result.push({t: 'address', v: data.contract});
21 | result.push({t: 'bytes32', v: data.govId});
22 | result.push({t: 'uint', v: data.suggestIndex.toString()});
23 | result.push({t: 'uint', v: data.swapIndex.toString()});
24 | result.push({t: 'address[]', v: data.validators});
25 | result.push({t: 'bytes32[]', v: data.signatureHashs});
26 | result.push({t: 'uint', v: data.fee.toString()});
27 | result.push({t: 'uint', v: data.seq.toString()});
28 |
29 | return result;
30 | };
31 |
32 | exports.packSigningHash = function(data) {
33 | let result = [];
34 |
35 | result.push({t: 'address', v: data.contract});
36 | result.push({t: 'bytes32', v: data.govId});
37 | result.push({t: 'uint', v: data.selectionIndex});
38 | result.push({t: 'bytes32[]', v: data.signatureHashs});
39 |
40 | return result;
41 | };
42 |
43 | exports.packXrpTagHash = function(data) {
44 | let result = [];
45 |
46 | result.push({t: 'string', v: 'XRP'});
47 | result.push({t: 'string', v: 'AddressBook'});
48 | result.push({t: 'uint256', v: data.version});
49 | result.push({t: 'string', v: data.toChain});
50 | result.push({t: 'bytes', v: toHexBuffer(data.toAddress)});
51 | result.push({t: 'bytes', v: toHexBuffer(data.transfortData)});
52 |
53 | return result;
54 | }
55 |
56 | exports.packLimitationData = function(data) {
57 | let result = [];
58 |
59 | result.push({t: 'string', v: "GateKeeper"});
60 | result.push({t: 'string', v: data.fromChain});
61 | result.push({t: 'string', v: data.toChain});
62 | result.push({t: 'bytes', v: toHexBuffer(data.token)});
63 | result.push({t: 'bytes32[]', v: data.bytes32s});
64 | result.push({t: 'uint[]', v: data.uints});
65 |
66 | return result;
67 | }
68 |
69 | function toHexBuffer(str) {
70 | return Buffer.from(str.replace('0x', ""), 'hex');
71 | }
72 |
--------------------------------------------------------------------------------
/src/xrp/utils/ripple.api.js:
--------------------------------------------------------------------------------
1 | const RippleAPI = require('ripple-lib').RippleAPI;
2 | const config = require(ROOT + '/config');
3 | const info = config.info.xrp;
4 | const api = new RippleAPI({ server: info.ENDPOINT.socket, connectionTimeout: 60000 });
5 |
6 | module.exports = api;
7 | module.exports.getSequence = async address => {
8 | let accountInfo = await api.getAccountInfo(address).catch(e => {
9 | logger.xrp.error('getSequence error: ' + e.message);
10 | });
11 |
12 | if(!accountInfo)
13 | return;
14 |
15 | return accountInfo.sequence;
16 | };
17 |
18 | module.exports.getVaultInfos = async address => {
19 | const obj = await api.getAccountObjects(address).catch(e => {
20 | logger.xrp.error('getSequence error: ' + e.message);
21 | });
22 | if (!obj || obj.account_objects.length !== 1) {
23 | return;
24 | }
25 | return obj.account_objects[0];
26 | }
27 |
28 | module.exports.getBalance = async address => {
29 | let accountInfo = await api.getAccountInfo(address).catch(e => {
30 | logger.xrp.error('getSequence error: ' + e.message);
31 | });
32 |
33 | if(!accountInfo)
34 | return;
35 |
36 | return accountInfo.xrpBalance * 10 ** 6;
37 | };
38 |
--------------------------------------------------------------------------------
/src/xrp/utils/xrp.bridgeutils.js:
--------------------------------------------------------------------------------
1 | const BridgeUtils = require(ROOT + '/lib/bridgeutils');
2 | const crypto = require('crypto');
3 | const addressCodec = require('ripple-address-codec');
4 | const bs58 = require('bs58');
5 | const varuint = require('varuint-bitcoin');
6 | const ethUtil = require('ethereumjs-util');
7 | const codec = require('ripple-binary-codec');
8 | const keypairs = require('ripple-keypairs');
9 | const ripple = require('./ripple.api');
10 | const EC = require('elliptic').ec;
11 | const secp256k1 = new EC('secp256k1');
12 |
13 | let context = null;
14 |
15 | class XrpBridge extends BridgeUtils {
16 | constructor(network) {
17 | super();
18 | context = this;
19 | }
20 |
21 | getLength(str) {
22 | if (!str) {
23 | throw new TypeError('The parameter is empty.');
24 | }
25 |
26 | let len = 0;
27 | if (Buffer.isBuffer(str)) {
28 | str = str.toString('hex');
29 | }
30 |
31 | switch (typeof str) {
32 | case 'string':
33 | len = parseInt(str.length / 2);
34 | break;
35 | case 'number':
36 | len = parseInt(str);
37 | break;
38 | default:
39 | throw new TypeError('The parameter must be a string or a number');
40 | }
41 | return len;
42 | }
43 |
44 | getLengthHex(str) {
45 | let len = this.getLength(str);
46 |
47 | return varuint.encode(len).toString('hex');
48 | }
49 |
50 | toDER(x) {
51 | let buf = x;
52 | if (!Buffer.isBuffer(buf))
53 | buf = Buffer.from(x.replace('0x', ''), 'hex');
54 |
55 | const ZERO = Buffer.alloc(1, 0);
56 | let i = 0;
57 | while (buf[i] === 0) ++i;
58 | if (i === buf.length) return ZERO;
59 | buf = buf.slice(i);
60 | if (buf[0] & 0x80) return Buffer.concat([ZERO, buf], 1 + buf.length);
61 | return buf;
62 | }
63 |
64 | async generatePaymentTx(from, to, tag, drops, memos, quorum) {
65 | if (!from)
66 | throw 'Source address is invalid.';
67 | if (!to)
68 | throw 'Destination address is invalid.';
69 | if (!drops)
70 | throw 'amount(drops) is invalid.';
71 |
72 | let payment = {
73 | source: {
74 | address: from,
75 | maxAmount: {
76 | value: drops.toString(),
77 | currency: 'drops'
78 | }
79 | },
80 | destination: {
81 | address: to,
82 | amount: {
83 | value: drops.toString(),
84 | currency: 'drops'
85 | }
86 | }
87 | }
88 |
89 | if (tag)
90 | payment.destination.tag = parseInt(tag);
91 |
92 | if (memos)
93 | payment.memos = memos;
94 |
95 | let tx = await ripple.preparePayment(from, payment);
96 |
97 | if (tx) {
98 | let json = JSON.parse(tx.txJSON);
99 | if (json) {
100 | json.Fee = parseFloat(json.Fee);
101 |
102 | quorum = parseInt(quorum);
103 | if (!Number.isNaN(quorum) && quorum > 0) {
104 | json.SigningPubKey = '';
105 | json.Fee = parseFloat(json.Fee) * (1 + quorum);
106 | }
107 |
108 | json.Fee = (json.Fee).toString();
109 | delete json.LastLedgerSequence;
110 | }
111 |
112 | tx.txJSON = json;
113 | }
114 |
115 | return tx;
116 | }
117 |
118 | getAddress(pubKey) {
119 | return keypairs.deriveAddress(pubKey);
120 | }
121 |
122 | getKeyPair(pk) {
123 | let keyPair = {privateKey: pk};
124 | pk = null;
125 |
126 | keyPair.publicKey = Buffer.from(secp256k1.keyFromPrivate(keyPair.privateKey).getPublic().encodeCompressed()).toString('hex');
127 | keyPair.address = this.getAddress(keyPair.publicKey);
128 |
129 | return keyPair;
130 | }
131 |
132 | recoverPubKey(hash, v, r, s) {
133 | v = Number(v);
134 |
135 | if (Number.isNaN(v))
136 | v = 0;
137 | else if (v >= 27)
138 | v -= 27;
139 |
140 | hash = Buffer.from(hash.replace('0x', ''), 'hex');
141 | if (typeof r === 'string') {
142 | r = Buffer.from(r.replace('0x', ''), 'hex');
143 | }
144 | if (typeof s === 'string') {
145 | s = Buffer.from(s.replace('0x', ''), 'hex');
146 | }
147 |
148 | let xy = secp256k1.recoverPubKey(hash, {r, s}, v);
149 | return xy.encodeCompressed('hex');
150 | }
151 |
152 | getRawMultisigTx(txJson, signerAddress) {
153 | return this.encodeTxMultisig(txJson, signerAddress, true);
154 | }
155 |
156 | getSignatureHash(rawOrTxObject, signerAddress) {
157 | let rawTx = rawOrTxObject;
158 | if (typeof rawTx !== 'string' && typeof rawTx === 'object') {
159 | if (!rawTx.TransactionType)
160 | throw 'Invalid transaction object.';
161 |
162 | rawTx = this.getRawMultisigTx(rawTx, signerAddress)
163 | }
164 |
165 | let signingData = Buffer.from(rawTx, 'hex').toJSON().data;
166 | let hash = crypto.createHash('sha512').update(Buffer.from(signingData)).digest('hex');
167 |
168 | return hash.slice(0, 64);
169 | }
170 |
171 | getTxnSignature(r, s) {
172 | let sig = `02${this.getLengthHex(r)}${r}02${this.getLengthHex(s)}${s}`;
173 | sig = `30${this.getLengthHex(sig)}${sig}`;
174 |
175 | return sig;
176 | }
177 |
178 | ecsign(hash, pk) {
179 | if (!Buffer.isBuffer(hash))
180 | hash = Buffer.from(hash.replace('0x', ''), 'hex');
181 | if (!Buffer.isBuffer(pk))
182 | pk = Buffer.from(pk.replace('0x', ''), 'hex');
183 |
184 | let vrs = ethUtil.ecsign(hash, pk);
185 | pk = null;
186 |
187 | return {
188 | v: vrs.s,
189 | r: '0x' + vrs.r.toString('hex'),
190 | s: '0x' + vrs.s.toString('hex')
191 | }
192 | }
193 |
194 | getSerializedTx(txJson, signatureObject) {
195 | let tx = txJson;
196 | tx.SigningPubKey = '';
197 |
198 | let signer = {
199 | Account: signatureObject.account,
200 | SigningPubKey: signatureObject.publicKey.toUpperCase(),
201 | TxnSignature: signatureObject.txnSignature.toUpperCase()
202 | };
203 |
204 | tx.Signers = [{Signer: signer}];
205 |
206 | let serialized = codec.encode(tx);
207 | return serialized;
208 | }
209 |
210 | getAddressToHex(address, isBtcDigit) {
211 | let bytes = isBtcDigit ? bs58.decode(address) : addressCodec.codec.codec.decode(address);
212 | return '0x' + Buffer.from(bytes).toString('hex');
213 | }
214 |
215 | getAddressFromHex(hex, isBtcDigit) {
216 | let buf = Buffer.from(hex.replace('0x', ''), 'hex');
217 | return isBtcDigit ? bs58.encode(buf) : addressCodec.codec.codec.encode(buf);
218 | }
219 |
220 | encodeTxMultisig(txJson, signAs) {
221 | if (!signAs)
222 | throw 'signAs is not defined.';
223 |
224 | if (typeof txJson === 'string')
225 | txJson = JSON.parse(txJson);
226 |
227 | let hex = codec.encodeForMultisigning(txJson, signAs);
228 |
229 | return hex;
230 | }
231 |
232 | getReleaseMemo(govId, swapIndex) {
233 | let memos = [];
234 |
235 | memos.push({
236 | Memo: {
237 | MemoData: this.string2hex(swapIndex.toString()).toUpperCase(),
238 | MemoType: this.string2hex('swapIndex').toUpperCase()
239 | }
240 | });
241 |
242 | memos.push({
243 | Memo: {
244 | MemoData: this.string2hex(govId).toUpperCase(),
245 | MemoType: this.string2hex('govId').toUpperCase()
246 | }
247 | });
248 |
249 | return memos
250 | }
251 |
252 | string2hex(str) {
253 | var hex = '';
254 | for (var i = 0; i < str.length; i++) {
255 | hex += str.charCodeAt(i).toString(16);
256 | }
257 |
258 | return hex;
259 | }
260 | }
261 |
262 | module.exports = XrpBridge;
263 |
--------------------------------------------------------------------------------
/wallet.js:
--------------------------------------------------------------------------------
1 | let walletApi = require('ethereumjs-wallet');
2 | let ethUtil = require('ethereumjs-util');
3 | let hdKey = require('ethereumjs-wallet/hdkey');
4 | let fs = require('fs');
5 | let Web3 = require('web3');
6 | const web3 = new Web3();
7 | const path = require('path');
8 | const readline = require('readline-sync');
9 |
10 | class WalletUtil {
11 | static getKeystoreJSON(keyPath) {
12 | keyPath = keyPath || path.resolve() + '/keystore.json';
13 |
14 | let file = null;
15 |
16 | try {
17 | file = fs.readFileSync(keyPath, 'utf8');
18 | } catch (e) {
19 | throw e;
20 | }
21 |
22 | let json = {};
23 | try {
24 | json = JSON.parse(file);
25 | } catch (e) {
26 | throw e;
27 | }
28 |
29 | if (!json)
30 | throw 'No JSON type keystore.';
31 |
32 | if (json.Crypto)
33 | json.crypto = json.Crypto;
34 |
35 | return json;
36 | }
37 |
38 | static getWallet(keystore, password) {
39 | let wallet = walletApi.fromV3(keystore, password);
40 | return {
41 | address: wallet.getAddressString(),
42 | addressBuffer: wallet.getAddress(),
43 | pk: wallet.getPrivateKey().toString('hex'),
44 | pkBuffer: wallet.getPrivateKey()
45 | }
46 | }
47 |
48 | static getWalletFromPK(pk) {
49 | let wallet = walletApi.fromPrivateKey(pk);
50 | return {
51 | address: wallet.getAddressString(),
52 | addressBuffer: wallet.getAddress(),
53 | pk: wallet.getPrivateKey().toString('hex'),
54 | pkBuffer: wallet.getPrivateKey(),
55 | publicKey: wallet.getPublicKeyString()
56 | }
57 | }
58 | static makeWallet(seed, password, encryptCount) {
59 | let wallet = hdKey.fromMasterSeed(seed).getWallet();
60 |
61 | return wallet.toV3(password, {
62 | n: encryptCount || 8192
63 | });
64 | }
65 |
66 | static migrateWallet(pk, password, encryptCount) {
67 | pk = pk.replace('0x', '');
68 |
69 | if (pk === '') {
70 | let newaccount = web3.eth.accounts.create(web3.utils.randomHex(32));
71 | pk = newaccount.privateKey;
72 | if (password === ''){
73 | console.log(newaccount.address, pk);
74 | process.exit(0);
75 | }
76 | }
77 | let pkBuffer = ethUtil.toBuffer('0x' + pk.replace('0x', ''));
78 | let wallet = walletApi.fromPrivateKey(pkBuffer);
79 |
80 | return wallet.toV3(password, {
81 | n: encryptCount || 8192
82 | });
83 | }
84 | }
85 |
86 | if (process.argv[1].indexOf('wallet') !== -1) {
87 | let argvAccount = getAccountFromParams();
88 | if (argvAccount) {
89 | let keystore = WalletUtil.migrateWallet(argvAccount.pk, argvAccount.pw);
90 | let address = keystore.address;
91 | let filename = `keystore_${address}.json`;
92 |
93 | fs.writeFileSync('./' + filename, JSON.stringify(keystore), 'utf8');
94 | console.log('Keystore file saved: ' + filename);
95 | }
96 | }
97 |
98 | function getAccountFromParams() {
99 | if (process.argv.length < 2)
100 | return null;
101 |
102 | let pk = process.argv[2];
103 | let pw = process.argv[3];
104 |
105 | if (pk.length === 66) {
106 | pk = pk.replace('0x', '');
107 | } else if (pk === 'load') {
108 | let kpw = readline.question('Password: ', {
109 | hideEchoBack: true
110 | });
111 | try {
112 | console.log(WalletUtil.getWallet(WalletUtil.getKeystoreJSON(pw), kpw));
113 | process.exit(0);
114 | } catch (e) {
115 | console.log(e);
116 | }
117 | } else if (pk === '0x') {
118 | return {
119 | pk:'',
120 | pw:''
121 | }
122 | } else if (pk === 'new') {
123 | pk = ''
124 | } else if (pk.length !== 64) {
125 | throw 'Account private key must be 32Byte Hex.'
126 | }
127 |
128 | if (!pw || pw.length == 0) {
129 |
130 | pw = readline.question('Password: ', {
131 | hideEchoBack: true
132 | });
133 | if (pw.length == 0) {
134 | throw 'Password length muse be bigger than 1';
135 | }
136 | }
137 |
138 | return {
139 | pk: pk,
140 | pw: pw
141 | }
142 | }
143 |
144 | module.exports = WalletUtil;
145 |
--------------------------------------------------------------------------------