forked from renproject/multichain
-
Notifications
You must be signed in to change notification settings - Fork 0
/
multichain.go
540 lines (455 loc) · 16.7 KB
/
multichain.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
// Package multichain defines all supported assets and chains. It also
// re-exports the individual multichain APIs.
package multichain
import (
"github.com/renproject/multichain/api/account"
"github.com/renproject/multichain/api/address"
"github.com/renproject/multichain/api/contract"
"github.com/renproject/multichain/api/gas"
"github.com/renproject/multichain/api/utxo"
"github.com/renproject/surge"
)
type (
// An Address is a human-readable representation of a public identity. It can
// be the address of an external account, contract, or script.
Address = address.Address
// The AddressEncodeDecoder interfaces combines encoding and decoding
// functionality into one interface.
AddressEncodeDecoder = address.EncodeDecoder
// RawAddress is an address that has been decoded into its binary form.
RawAddress = address.RawAddress
)
type (
// The AccountTx interface defines the functionality that must be exposed by
// account-based transactions.
AccountTx = account.Tx
// The AccountTxBuilder interface defines the functionality required to build
// account-based transactions. Most chain implementations require additional
// information, and this should be accepted during the construction of the
// chain-specific transaction builder.
AccountTxBuilder = account.TxBuilder
// The AccountClient interface defines the functionality required to interact
// with a chain over RPC.
AccountClient = account.Client
)
type (
// A UTXOutpoint identifies a specific output produced by a transaction.
UTXOutpoint = utxo.Outpoint
// A UTXOutput is produced by a transaction. It includes the conditions
// required to spend the output (called the pubkey script, based on Bitcoin).
UTXOutput = utxo.Output
// A UTXOInput specifies an existing output, produced by a previous
// transaction, to be consumed by another transaction. It includes the script
// that meets the conditions specified by the consumed output (called the sig
// script, based on Bitcoin).
UTXOInput = utxo.Input
// A UTXORecipient specifies an address, and an amount, for which a
// transaction will produce an output. Depending on the output, the address
// can take on different formats (e.g. in Bitcoin, addresses can be P2PK,
// P2PKH, or P2SH).
UTXORecipient = utxo.Recipient
// A UTXOTx interfaces defines the functionality that must be exposed by
// utxo-based transactions.
UTXOTx = utxo.Tx
// A UTXOTxBuilder interface defines the functionality required to build
// account-based transactions. Most chain implementations require additional
// information, and this should be accepted during the construction of the
// chain-specific transaction builder.
UTXOTxBuilder = utxo.TxBuilder
// A UTXOClient interface defines the functionality required to interact with
// a chain over RPC.
UTXOClient = utxo.Client
)
type (
// ContractCallData is used to specify a function and its parameters when
// invoking business logic on a contract.
ContractCallData = contract.CallData
// The ContractCaller interface defines the functionality required to call
// readonly functions on a contract. Calling functions that mutate contract
// state should be done using the Account API.
ContractCaller = contract.Caller
)
type (
// The GasEstimator interface defines the functionality required to know the
// current recommended gas prices.
GasEstimator = gas.Estimator
)
// An Asset uniquely identifies assets using human-readable strings.
type Asset string
// Enumeration of supported assets. When introducing a new chain, or new asset
// from an existing chain, you must add a human-readable string to this set of
// enumerated values. Assets must be listed in alphabetical order.
const (
ArbETH = Asset("ArbETH") // Arbitrum Ether
AVAX = Asset("AVAX") // Avalanche
BCH = Asset("BCH") // Bitcoin Cash
BNB = Asset("BNB") // Binance Coin
BTC = Asset("BTC") // Bitcoin
DGB = Asset("DGB") // DigiByte
DOGE = Asset("DOGE") // Dogecoin
ETH = Asset("ETH") // Ether
FIL = Asset("FIL") // Filecoin
FTM = Asset("FTM") // Fantom
GLMR = Asset("GLMR") // Glimmer
KAVA = Asset("KAVA") // Kava
LUNA = Asset("LUNA") // Luna
MATIC = Asset("MATIC") // Matic PoS (Polygon)
SOL = Asset("SOL") // Solana
ZEC = Asset("ZEC") // Zcash
BADGER = Asset("BADGER") // Badger DAO
BUSD = Asset("BUSD") // Binance USD
CRV = Asset("CRV") // Curve
DAI = Asset("DAI") // Dai
EURT = Asset("EURT") // Euro Tether
FTT = Asset("FTT") // FTX
ibBTC = Asset("ibBTC") // Interest Bearing Bitcoin
KNC = Asset("KNC") // Kyber Network
LINK = Asset("LINK") // Chainlink
MIM = Asset("MIM") // Magic Internet Money
REN = Asset("REN") // Ren
ROOK = Asset("ROOK") // KeeperDAO
SUSHI = Asset("SUSHI") // Sushiswap
UNI = Asset("UNI") // Uniswap
USDC = Asset("USDC") // Circle USD
USDT = Asset("USDT") // Tether
// These assets are defined separately because their purpose is to help us
// differentiate between different testnets for the same blockchain.
KETH = Asset("KETH") // Kovan ETH
GETH = Asset("GETH") // Goerli ETH
// These assets are defined separately because they are mock assets. These
// assets should only be used for testing.
AMOCK1 = Asset("AMOCK1") // Account-based mock asset
AMOCK2 = Asset("AMOCK2") // Account-based mock asset
AMOCK3 = Asset("AMOCK3") // ERC-20 mock token asset on chain AccountMocker1
UMOCK = Asset("UMOCK") // UTXO-based mock asset
)
// AssetType represents the type of asset, whether native-asset of an account
// chain or a token on an account chain.
type AssetType string
const (
// AssetTypeNative is an identifier for all the native assets of account
// based chains namely. For instance, ETH for Ethereum, BNB for
// BinanceSmartChain.
AssetTypeNative = AssetType("NativeAsset")
// AssetTypeToken is an identifier for all tokens (ERC20, BEP20) deployed on
// programmable account-based chains. For instance, REN and USDC are ERC-20
// tokens on Ethereum.
AssetTypeToken = AssetType("TokenAsset")
)
// SizeHint returns the number of bytes required to represent the asset type in
// binary.
func (assetType AssetType) SizeHint() int {
return surge.SizeHintString(string(assetType))
}
// Marshal the asset type to binary. You should not call this function directly,
// unless you are implementing marshalling for a container type.
func (assetType AssetType) Marshal(buf []byte, rem int) ([]byte, int, error) {
return surge.MarshalString(string(assetType), buf, rem)
}
// Unmarshal the asset type from binary. You should not call this function
// directly, unless you are implementing unmarshalling for a container type.
func (assetType *AssetType) Unmarshal(buf []byte, rem int) ([]byte, int, error) {
return surge.UnmarshalString((*string)(assetType), buf, rem)
}
// OriginChain returns the chain upon which the asset originates. For example,
// the origin chain of BTC is Bitcoin.
func (asset Asset) OriginChain() Chain {
switch asset {
case ArbETH:
return Arbitrum
case AVAX:
return Avalanche
case BCH:
return BitcoinCash
case BNB:
return BinanceSmartChain
case BTC:
return Bitcoin
case DGB:
return DigiByte
case DOGE:
return Dogecoin
case ETH:
return Ethereum
case FIL:
return Filecoin
case FTM:
return Fantom
case GLMR:
return Moonbeam
case KAVA:
return Kava
case LUNA:
return Terra
case MATIC:
return Polygon
case SOL:
return Solana
case ZEC:
return Zcash
case BADGER, BUSD, CRV, DAI, EURT, FTT, ibBTC, KNC, LINK, MIM, REN, ROOK,
SUSHI, UNI, USDC, USDT:
return Ethereum
case KETH:
return Kovan
case GETH:
return Goerli
// These assets are handled separately because they are mock assets. These
// assets should only be used for testing.
case AMOCK1, AMOCK3:
return AccountMocker1
case AMOCK2:
return AccountMocker2
case UMOCK:
return UTXOMocker
default:
return Chain("")
}
}
// ChainType returns the chain-type (Account or UTXO) for the given asset
func (asset Asset) ChainType() ChainType {
switch asset {
case BCH, BTC, DGB, DOGE, ZEC:
return ChainTypeUTXOBased
case ArbETH, AVAX, BNB, ETH, FIL, FTM, GLMR, KAVA, LUNA, MATIC, SOL:
return ChainTypeAccountBased
case BADGER, BUSD, CRV, DAI, EURT, FTT, ibBTC, KNC, LINK, MIM, REN, ROOK,
SUSHI, UNI, USDC, USDT:
return ChainTypeAccountBased
case KETH, GETH:
return ChainTypeAccountBased
// These assets are handled separately because they are mock assets. These
// assets should only be used for testing.
case AMOCK1, AMOCK2, AMOCK3:
return ChainTypeAccountBased
case UMOCK:
return ChainTypeUTXOBased
default:
return ChainType("")
}
}
// Type returns the asset-type (Native or Token) for the given asset.
func (asset Asset) Type() AssetType {
switch asset {
case ArbETH, AVAX, BNB, ETH, FTM, GLMR, KAVA, MATIC, SOL:
return AssetTypeNative
case BADGER, BUSD, CRV, DAI, EURT, FTT, ibBTC, KNC, LINK, MIM, REN, ROOK,
SUSHI, UNI, USDC, USDT:
return AssetTypeToken
case KETH, GETH:
return AssetTypeNative
// These assets are handled separately because they are mock assets. These
// assets should only be used for testing.
case AMOCK1, AMOCK2:
return AssetTypeNative
case AMOCK3:
return AssetTypeToken
default:
return AssetType("")
}
}
// SizeHint returns the number of bytes required to represent the asset in
// binary.
func (asset Asset) SizeHint() int {
return surge.SizeHintString(string(asset))
}
// Marshal the asset to binary.
func (asset Asset) Marshal(buf []byte, rem int) ([]byte, int, error) {
return surge.MarshalString(string(asset), buf, rem)
}
// Unmarshal the asset from binary.
func (asset *Asset) Unmarshal(buf []byte, rem int) ([]byte, int, error) {
return surge.UnmarshalString((*string)(asset), buf, rem)
}
// A Chain uniquely identifies a blockchain using a human-readable string.
type Chain string
// Enumeration of supported chains. When introducing a new chain, you must add a
// human-readable string to this set of enumerated values. Chains must be listed
// in alphabetical order.
const (
Arbitrum = Chain("Arbitrum")
Avalanche = Chain("Avalanche")
BinanceSmartChain = Chain("BinanceSmartChain")
Bitcoin = Chain("Bitcoin")
BitcoinCash = Chain("BitcoinCash")
DigiByte = Chain("DigiByte")
Dogecoin = Chain("Dogecoin")
Ethereum = Chain("Ethereum")
Fantom = Chain("Fantom")
Filecoin = Chain("Filecoin")
Kava = Chain("Kava")
Moonbeam = Chain("Moonbeam")
Polygon = Chain("Polygon")
Ren = Chain("Ren")
Solana = Chain("Solana")
Terra = Chain("Terra")
Zcash = Chain("Zcash")
Kovan = Chain("Kovan")
Goerli = Chain("Goerli")
// These chains are defined separately because they are mock chains. These
// chains should only be used for testing.
AccountMocker1 = Chain("AccountMocker1")
AccountMocker2 = Chain("AccountMocker2")
UTXOMocker = Chain("UTXOMocker")
)
// SizeHint returns the number of bytes required to represent the chain in
// binary.
func (chain Chain) SizeHint() int {
return surge.SizeHintString(string(chain))
}
// Marshal the chain to binary. You should not call this function directly,
// unless you are implementing marshalling for a container type.
func (chain Chain) Marshal(buf []byte, rem int) ([]byte, int, error) {
return surge.MarshalString(string(chain), buf, rem)
}
// Unmarshal the chain from binary. You should not call this function directly,
// unless you are implementing unmarshalling for a container type.
func (chain *Chain) Unmarshal(buf []byte, rem int) ([]byte, int, error) {
return surge.UnmarshalString((*string)(chain), buf, rem)
}
// ChainType returns the chain type (whether account-based or utxo-based chain)
// for the chain.
func (chain Chain) ChainType() ChainType {
switch chain {
case Bitcoin, BitcoinCash, DigiByte, Dogecoin, Zcash:
return ChainTypeUTXOBased
case Avalanche, BinanceSmartChain, Ethereum, Arbitrum, Fantom, Filecoin,
Kava, Moonbeam, Polygon, Ren, Solana, Terra:
return ChainTypeAccountBased
case Kovan, Goerli:
return ChainTypeAccountBased
// These chains are handled separately because they are mock chains. These
// chains should only be used for testing.
case AccountMocker1, AccountMocker2:
return ChainTypeAccountBased
case UTXOMocker:
return ChainTypeUTXOBased
default:
return ChainType("")
}
}
// IsAccountBased returns true when invoked on an account-based chain, otherwise
// returns false.
func (chain Chain) IsAccountBased() bool {
return chain.ChainType() == ChainTypeAccountBased
}
// IsUTXOBased returns true when invoked on a utxo-based chain, otherwise
// returns false.
func (chain Chain) IsUTXOBased() bool {
return chain.ChainType() == ChainTypeUTXOBased
}
// NativeAsset returns the underlying native asset for a chain. For example, the
// root asset of Bitcoin chain is BTC.
func (chain Chain) NativeAsset() Asset {
switch chain {
case Avalanche:
return AVAX
case BinanceSmartChain:
return BNB
case BitcoinCash:
return BCH
case Bitcoin:
return BTC
case DigiByte:
return DGB
case Dogecoin:
return DOGE
case Ethereum:
return ETH
case Fantom:
return FTM
case Filecoin:
return FIL
case Kava:
return KAVA
case Moonbeam:
return GLMR
case Polygon:
return MATIC
case Solana:
return SOL
case Terra:
return LUNA
case Zcash:
return ZEC
case Arbitrum:
return ArbETH
case Kovan:
return KETH
case Goerli:
return GETH
// These chains are handled separately because they are mock chains. These
// chains should only be used for testing.
case AccountMocker1:
return AMOCK1
case AccountMocker2:
return AMOCK2
case UTXOMocker:
return UMOCK
default:
return Asset("")
}
}
// ChainType represents the type of chain (whether account-based or utxo-based)
type ChainType string
const (
// ChainTypeAccountBased is an identifier for all account-based chains,
// namely, BinanceSmartChain, Ethereum, Filecoin, and so on.
ChainTypeAccountBased = ChainType("Account")
// ChainTypeUTXOBased is an identifier for all utxo-based chains, namely,
// Bitcoin, BitcoinCash, DigiByte, and so on.
ChainTypeUTXOBased = ChainType("UTXO")
)
// SizeHint returns the number of bytes required to represent the chain type in
// binary.
func (chainType ChainType) SizeHint() int {
return surge.SizeHintString(string(chainType))
}
// Marshal the chain type to binary. You should not call this function directly,
// unless you are implementing marshalling for a container type.
func (chainType ChainType) Marshal(buf []byte, rem int) ([]byte, int, error) {
return surge.MarshalString(string(chainType), buf, rem)
}
// Unmarshal the chain type from binary. You should not call this function
// directly, unless you are implementing unmarshalling for a container type.
func (chainType *ChainType) Unmarshal(buf []byte, rem int) ([]byte, int, error) {
return surge.UnmarshalString((*string)(chainType), buf, rem)
}
// Network identifies the network type for the multichain deployment
type Network string
const (
// NetworkLocalnet represents a local network for chains. It is usually only
// accessible from the device running the network, and is not accessible
// over the Internet. Chain rules are often slightly different to allow for
// faster block times and easier access to testing funds. This is also
// sometimes referred to as "regnet" or "regression network". It should only
// be used for local testing.
NetworkLocalnet = Network("localnet")
// NetworkDevnet represents the development network for chains. This network
// is typically a deployed version of the localnet. Chain rules are often
// slightly different to allow for faster block times and easier access to
// testing funds.
NetworkDevnet = Network("devnet")
// NetworkTestnet represents the test network for chains. This network is
// typically a publicly accessible network that has the same, or very
// similar, chain rules compared to mainnet. Assets on this type of network
// are usually not considered to have value.
NetworkTestnet = Network("testnet")
// NetworkMainnet represents the main network for chains.
NetworkMainnet = Network("mainnet")
)
// SizeHint returns the number of bytes required to represent the network in
// binary.
func (net Network) SizeHint() int {
return surge.SizeHintString(string(net))
}
// Marshal the network to binary. You should not call this function directly,
// unless you are implementing marshalling for a container type.
func (net Network) Marshal(buf []byte, rem int) ([]byte, int, error) {
return surge.MarshalString(string(net), buf, rem)
}
// Unmarshal the network from binary. You should not call this function
// directly, unless you are implementing unmarshalling for a container type.
func (net *Network) Unmarshal(buf []byte, rem int) ([]byte, int, error) {
return surge.UnmarshalString((*string)(net), buf, rem)
}