Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Rehearsal] Merge "mx-sdk-specs" into "mx-specs" #52

Draft
wants to merge 87 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
22fd981
Initial commit
andreibancioiu Jun 29, 2023
f44cadd
Initial commit.
andreibancioiu Jun 29, 2023
3d131b9
Add empty files for network providers.
andreibancioiu Jun 29, 2023
ce3c14f
Sketch factory.
andreibancioiu Jun 29, 2023
d91c917
Further work.
andreibancioiu Jun 29, 2023
24acf76
Amount and token transfer.
andreibancioiu Jun 29, 2023
dc061a9
Renaming on transaction factory.
andreibancioiu Jun 29, 2023
e80c2b3
Factories - sketch.
andreibancioiu Jun 30, 2023
027776b
Signers - sketch.
andreibancioiu Jun 30, 2023
98d6fac
Add verifiers.
andreibancioiu Jun 30, 2023
4a9c75a
Fix after review.
andreibancioiu Jun 30, 2023
0d923b0
Fix after review.
andreibancioiu Jun 30, 2023
35e23bb
Added new named constructor.
andreibancioiu Jun 30, 2023
6670128
Add some links with implementation examples.
andreibancioiu Jul 3, 2023
883c172
Sketch user wallet.
andreibancioiu Jul 3, 2023
e29ebe6
Update guidelines.
andreibancioiu Jul 4, 2023
eb273f2
Init sdk-wallet.
andreibancioiu Jul 4, 2023
5099607
Further work ("crypto" etc.).
andreibancioiu Jul 4, 2023
6d03426
Further work.
andreibancioiu Jul 4, 2023
cc910f7
Further work (keystores) etc.
andreibancioiu Jul 5, 2023
9df1a84
Add examples of usage etc.
andreibancioiu Jul 5, 2023
1012030
Extra examples, renamings etc.
andreibancioiu Jul 5, 2023
e273fda
Add usage example.
andreibancioiu Jul 5, 2023
e306cb0
Fix after self review.
andreibancioiu Jul 5, 2023
2d861bb
Adjust readme.
andreibancioiu Jul 5, 2023
3cda74d
Fix after review (part 1).
andreibancioiu Jul 6, 2023
1ce8a14
Fix after review (part 2).
andreibancioiu Jul 6, 2023
6fa37c0
Fix after review, remove "generate_keypair_with_constraint".
andreibancioiu Jul 7, 2023
30a1934
Fix after review, added string literal instead of constant.
andreibancioiu Jul 10, 2023
8f0818f
Merge pull request #3 from multiversx/init-sdk-wallet
andreibancioiu Jul 10, 2023
127415d
Removed sdk-wallet - to be taken from "main" branch.
andreibancioiu Jul 11, 2023
715f127
Merge branch 'main' into init
andreibancioiu Jul 11, 2023
a5eba98
Fix after review (partial).
andreibancioiu Jul 11, 2023
b271131
Sketch message.
andreibancioiu Jul 11, 2023
b14c792
TokenManagementTransactionsFactory - more operations.
andreibancioiu Jul 14, 2023
3f6169a
Fix after review (add params on delegation txs factory).
andreibancioiu Jul 14, 2023
7fd089d
Define SC txs factory.
andreibancioiu Jul 14, 2023
64226b3
Adjust readme.
andreibancioiu Jul 14, 2023
6334c42
Removed empty files.
andreibancioiu Jul 14, 2023
a71b3f1
Merge pull request #1 from multiversx/init
andreibancioiu Jul 21, 2023
c6b5396
add missing parmeters
popenta Jul 27, 2023
69e5e66
Merge pull request #5 from multiversx/fix-issue-fungible-params
andreibancioiu Aug 9, 2023
55e732d
Mention `any` for golang 1.18
camilbancioiu Aug 18, 2023
d2815dd
Merge pull request #7 from multiversx/go-1.18-any
camilbancioiu Aug 18, 2023
e506eb6
rename factory classes
popenta Aug 25, 2023
5eeeed3
update comments
popenta Aug 25, 2023
6fab3aa
Merge pull request #8 from multiversx/rename-factory-classes
popenta Aug 25, 2023
38fc407
rename factory files
popenta Aug 25, 2023
28cc961
Merge pull request #9 from multiversx/rename-factory-files
popenta Aug 25, 2023
db783ef
Rename folder.
andreibancioiu Sep 8, 2023
00ebe44
Rename folder.
andreibancioiu Sep 12, 2023
bff3102
Merge pull request #14 from multiversx/rename-folder
andreibancioiu Sep 12, 2023
28aaead
Transaction.guardianSignature should be optional.
andreibancioiu Sep 12, 2023
c2b4b78
Sketch: CustomToken, CustomTokenTransfer.
andreibancioiu Sep 12, 2023
94fca73
Sketch "TransferIntentsFactory".
andreibancioiu Sep 13, 2023
7320169
Sketch some changes for "amount".
andreibancioiu Sep 13, 2023
165ea3b
Redefine amount.
andreibancioiu Sep 13, 2023
b71c16c
Merge branch 'main' into transfer-and-execute
andreibancioiu Sep 13, 2023
041fad7
Remove file.
andreibancioiu Sep 13, 2023
c98f97c
Fix after review.
andreibancioiu Sep 15, 2023
22f61ac
Fix after review.
andreibancioiu Sep 15, 2023
996d86f
Fix after review.
andreibancioiu Sep 15, 2023
7f3eb24
Update parameter name.
andreibancioiu Sep 15, 2023
fe338cf
Merge pull request #15 from multiversx/transfer-and-execute
andreibancioiu Sep 19, 2023
85109f6
Rename files, methods.
andreibancioiu Sep 27, 2023
112e713
More details for transaction, draftTransaction.
andreibancioiu Sep 27, 2023
f65d3f8
Merge pull request #19 from multiversx/tx-vs-draft
andreibancioiu Sep 27, 2023
e815a7c
CustomTokenComputer: define errors. Rename methods, add some optional…
andreibancioiu Sep 28, 2023
aa752dd
Fix after review.
andreibancioiu Sep 28, 2023
9a6cbd0
Merge pull request #20 from multiversx/tokens-follow-up-28
andreibancioiu Sep 28, 2023
caa7b80
remove create zero address from factory
popenta Sep 29, 2023
c092834
Merge pull request #22 from multiversx/remove-address-zero
popenta Oct 2, 2023
6aec460
add chain id for DraftTransaction and renamed file
popenta Oct 27, 2023
af35f7c
Merge pull request #28 from multiversx/add-chain-id-for-draft-tx
popenta Oct 27, 2023
4b40d6c
add delegation operations
popenta Nov 17, 2023
97e134d
rename parameter
popenta Nov 17, 2023
c8a956d
another renaming
popenta Nov 17, 2023
5b21137
Merge pull request #29 from multiversx/add-delegation-operations
popenta Nov 22, 2023
e067510
Fix names, move behavior (functions), add extra comments.
andreibancioiu Dec 8, 2023
bc6cfc2
Fix after review. Also introduced MnemonicComputer.
andreibancioiu Dec 8, 2023
cf82c9e
Fix after review.
andreibancioiu Dec 11, 2023
7914cce
Merge pull request #31 from multiversx/updates-12-08
andreibancioiu Dec 11, 2023
78fdc6e
add relayed transaction factory
popenta Dec 18, 2023
7e16b04
add inner tx gas limit parameter for relayed v2
popenta Dec 19, 2023
6207a19
fixes after review
popenta Dec 19, 2023
6d98667
Merge pull request #37 from multiversx/relayed-transactions-factory
popenta Dec 19, 2023
57df70c
Merge remote-tracking branch 'sdk-specs/main' into merge-sdk-specs
andreibancioiu Dec 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions network-interaction-sdk/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2023 MultiversX

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
49 changes: 49 additions & 0 deletions network-interaction-sdk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Specifications for mx-sdk-* libraries

This repository contains specifications for the `mx-sdk-*` libraries. The specifications are written in a language-agnostic manner, and are meant to be implemented in multiple languages (e.g. Go, TypeScript, Python, Rust, etc.).

## Structure

- `sdk-core`: core components (address, transaction, etc.).
- `sdk-wallet`: core wallet components (generation, signing).
- `sdk-network-providers`: Network Provider (API, Gateway) components.

Below, we add specific details for some of the most important packages and sub-components.

### Transactions Factories

These components are located in `sdk-core/transactions-factories` and are responsible with creating transactions for specific use cases. They are designed as _multi-factory_ classes, having methods that return a `Transaction` object constructed by following specific recipes (with respect to the Protocol).

The methods are named in correspondence with the use cases they implement, e.g. `create_transaction_for_native_transfer()` or `create_transaction_for_new_delegation_contract()`. They return a `Transaction` (data transfer object), where `sender`, `receiver`, `value`, `data` and `gasLimit` are properly set (upon eventual computation, where applicable).

Optionally, the implementing library can choose to return an object that isn't a complete representation of the `Transaction`, if desired. In this case, the library must name the incomplete representation `DraftTransaction`, and also must provide a direct conversion facility from `DraftTransaction` to `Transaction` - for example, a named constructor. See [transaction](sdk-core/transaction.md).

## Guidelines

### **`in-ifaces-out-concrete-types`**

Generally speaking, it's recommended to receive input parameters as abstractions (interfaces) in the public API of the SDKs. This leads to an improved decoupling, and allows for easier type substitution (e.g. easier mocking, testing).

Generally speaking, it's recommended to return concrete types in the public API of the SDKs. The client code is responsible with decoupling from unnecessary data and behaviour of returned objects (e.g. by using interfaces, on their side). The only notable exception to this is when working with factories (abstract or method factories) that should have the function output an interface type. For example, have a look over `(User|Validator)WalletProvider.generate_keypair()` - this method returns abstract types (interfaces).

### **`pay-attention-to-types`**

- For JavaScript / TypeScript, `bytes` should be `Uint8Array`.

### **`follow-language-conventions`**

- Make sure to follow the naming conventions of the language you're using, e.g. `snake_case` vs. `camelCase`.
- In the specs, interfaces are prefixed with `I`, simply to make them stand out. However, in the implementing libraries, this convention does not have to be applied.
- In `go`, the term `serialize` (whether it's part of a class name or a function name) can be replaced by `marshal`, since that is the convention.
- Errors should also follow the language convention - e.g. `ErrInvalidPublicKey` vs `InvalidPublicKeyError`. Should have the same error message in all implementing libraries, though.

## **`any-object`**

In the specs, `object` is used as a placeholder for any type of object. In the implementing libraries, this would be replaced with the most appropriate type. For example:

- in Go:
- before Go 1.18: `map[string]interface{}` or directly `interface{}` (depending on the context)
- after Go 1.18: `map[string]any` or directly `any` (depending on the context)
- in Python: `dict` or `Any`
- in JavaScript / TypeScript: `object` or `any`

99 changes: 99 additions & 0 deletions network-interaction-sdk/sdk-core/address.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
## Address

```
class Address:
// Should also validate the length of the provided input.
// Can throw:
// - ErrInvalidPublicKey
constructor(public_key: bytes, hrp: string);

// Named constructor
// Can throw:
// - ErrInvalidBech32Address
static new_from_bech32(value: string): Address;

// Named constructor
// Can throw:
// - ErrInvalidHexString
static new_from_hex(value: string, hrp: string): Address;

// Returns the address as a string (bech32).
// Name should be adjusted to match the language's convention.
to_bech32(): string;

// Returns the address as a string (hex).
// Name should be adjusted to match the language's convention.
to_hex(): string;

// Returns the underlying public key.
get_public_key(): bytes;

// Returns the human-readable part of the address.
get_hrp(): string;

// Returns true if the address is a smart contract address.
is_smart_contract(): bool;
```

Example of usage:

```
address = Address.new_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th")

print("Address (bech32-encoded)", address.bech32())
print("Public key (hex-encoded):", address.hex())
```

## AddressFactory

```
class AddressFactory:
constructor(hrp: string = "erd");

// Creates an address from a bech32 string.
create_from_bech32(value: string): Address;

// Creates an address from a public key.
create_from_public_key(public_key: bytes): Address;

// Creates an address from a hex string.
create_from_hex(value: string): Address;
```

Example of usage:

```

factory = AddressFactory("erd")

address = factory.create_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th")
address = factory.create_from_hex("0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1")
address = factory.create_from_public_key(bytes.fromhex("0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1"))
```

## AddressComputer

```
class AddressComputer:
// The constructor is not captured by the specs; it's up to the implementing library to define it.

// Note that the first input parameter is received as an interface, but the return value is a concrete type (see guidelines).
compute_contract_address(deployer: IAddress, deployment_nonce: number): Address;

// The number of shards (necessary for computing the shard ID) would be received as a constructor parameter - constructor is not captured by specs.
get_shard_of_address(address: IAddress): number;
```

Above, `IAddress` should satisfy:

```
get_public_key(): bytes;
get_hrp(): string;
```

OR, perhaps, it should simply satisfy:

```
// Name should be adjusted to match the language's convention.
to_bech32(): string;
```
54 changes: 54 additions & 0 deletions network-interaction-sdk/sdk-core/amount.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
## Amount

Generally speaking, the `Amount` type should be:
- `int` in Python
- `big.Int` or `string` in Go
- `BigNumber.Value` (which includes `string`) in JavaScript

The implementing library can define type aliases, if desired, for example:

```Python
Amount = int
```

```Go
type Amount = big.Int
```

```JavaScript
type Amount = BigNumber.Value
```

Furthermore, the implementing library is free to define a wrapper class or structure. This isn't a requirement though. Example:

```
class Amount:
value: (big.Int|bigNumber|string)
to_string(): string
```

Within the specs, we use `Amount` and we mean `(bigNumber|string)`. Or, to put it differently, `(Go[big.Int]|Python[int]|JavaScript[BigNumber.Value|string])`.

**Important:**
- the value of an `Amount` is **always expressed in atomic units**. For example, to represent 1 EGLD, the value of `Amount` should be `1000000000000000000`, whether it's a Go `big.Int`, a Python `int`, a `string` etc.
- `Amount` **must not be concerned** with the number of decimals of the token. Just as the Protocol itself isn't concerned with this.

## AmountInUnits

Generally speaking, the `AmountInUnits` type should always be a `string`, so that **computations based on `AmountInUnits` are discouraged**. This type is meant to be used in the higher layers of an application, for example, on display purposes.

The implementing library can define type aliases or wrapper classes (structures), if desired. See above.

## AmountComputer

```
class AmountComputer:
// The constructor is not captured by the specs; it's up to the implementing library to define it.
// For example, the constructor can be parametrized with the decimals separator (e.g. "." or ",") and with the number of decimals of the native token (18).

amount_to_units(amount: Amount, num_decimals: number): AmountInUnits;
units_to_amount(units: AmountInUnits, num_decimals: number): Amount;

native_amount_to_units(amount: Amount): AmountInUnits;
native_units_to_amount(units: AmountInUnits): Amount;
```
26 changes: 26 additions & 0 deletions network-interaction-sdk/sdk-core/message.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
## Message

```
dto Message:
data: bytes;
signature: bytes;
```

## MessageComputer

```
class MessageComputer:
compute_bytes_for_signing(message: Message): bytes;
```

Reference implementation of `compute_bytes_for_signing`:

```
compute_bytes_for_signing(message: Message):
PREFIX = bytes.fromhex("17456c726f6e64205369676e6564204d6573736167653a0a")
size = length of message.data, encoded as a string
content = concat(PREFIX, size, message.data)
content_hash = keccak(digest_bits=256)

return content_hash
```
68 changes: 68 additions & 0 deletions network-interaction-sdk/sdk-core/tokens.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
## Token

```
dto Token:
// E.g. "FOO-abcdef", "EGLD".
identifier: string;
nonce: number;
```

## TokenComputer

```
class TokenComputer:
// The constructor is not captured by the specs; it's up to the implementing library to define it.

// Returns token.nonce == 0.
is_fungible(token: Token): boolean;

// Given "FOO-abcdef-0a" returns 10.
// Can throw:
// - ErrInvalidTokenIdentifier
extract_nonce_from_extended_identifier(extended_identifier: string): number;

// Given "FOO-abcdef-0a" returns "FOO-abcdef".
// Can throw:
// - ErrInvalidTokenIdentifier
extract_identifier_from_extended_identifier(extended_identifier: string): string;

// Given "FOO-abcdef-0a" returns "FOO".
// Given "FOO-abcdef" returns "FOO".
// Can throw:
// - ErrInvalidTokenIdentifier
extract_ticker_from_identifier(identifier: string): string;

// Optionally, the implementing library can define a method for parsing all token parts at once.
// The return type can be a tuple or the struct `TokenIdentifierParts` (see below).
// Can throw:
// - ErrInvalidTokenIdentifier
parse_extended_identifier_parts(identifier: string): TokenIdentifierParts;

// Given "FOO-abcdef" and 10 returns "FOO-abcdef-0a". If nonce is 0, returns "FOO-abcdef".
// For example, useful when preparing the parameters for querying token data from a network provider.
compute_extended_identifier_from_identifier_and_nonce(identifier: string, nonce: number): string;

// Optional, if `parse_extended_identifier_parts()` is also implemented.
// Pick one of the following (if the language does not support overloading):
compute_extended_identifier_from_parts(ticker: string, random_sequence: string, nonce: number): string;
compute_extended_identifier_from_parts(parts: TokenIdentifierParts): string;
```

An optional structure, if the implementing library defines a `parse_extended_identifier_parts` method:

```
dto TokenIdentifierParts:
ticker: string;
random_sequence: string;
nonce: number;
```

## TokenTransfer

```
dto TokenTransfer:
token: Token;

// Always in atomic units, e.g. for transferring 1.000000 "USDC-c76f1f", it must be "1000000".
amount: Amount;
```
49 changes: 49 additions & 0 deletions network-interaction-sdk/sdk-core/transaction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
## Transaction

```
dto Transaction:
sender: string;
receiver: string;
gasLimit: uint32;
chainID: string;

nonce?: uint64;
value?: Amount;
senderUsername?: string;
receiverUsername?: string;
gasPrice?: uint32;

data?: bytes;
version?: uint32;
options?: uint32;
guardian?: string;

signature: bytes;
guardianSignature?: bytes;

// Optional named constructor, if and only if the implementing library defines a `DraftTransaction`.
new_from_draft(draft: DraftTransaction): Transaction;
```

## DraftTransaction

Optionally, if desired, the implementing library can also define an incomplete representation of the transaction, to be used as return type for the **transaction factories**. See [README](../README.md), instead of the `Transaction` type.

```
dto DraftTransaction:
sender: string;
receiver: string;
value?: string;
data?: bytes;
gasLimit: uint32;
chainID: string; // The chain ID from the factory's config (received in the constructor) should be used
```

## TransactionComputer

```
class TransactionComputer:
compute_transaction_fee(transaction: Transaction, network_config: INetworkConfig): Amount;
compute_bytes_for_signing(transaction: Transaction): bytes;
compute_transaction_hash(transaction: Transaction): bytes;
```
Loading