<!-- livebook:{"default_language":"erlang","file_entries":[{"name":"logo_web3_aptos_ex.png","type":"attachment"},{"name":"web3_aptos_ex.png","type":"attachment"}],"persist_outputs":true} -->
# Web3AptosEx
## 0x00 Description
![](files/logo_web3_aptos_ex.png)
Aptos SDK impl in elixir!
![](files/web3_aptos_ex.png)
See the using example in:
> https://github.com/NonceGeek/move_sdk_ex_liveview_example
## 0x01 Implementation
* [x] Aptos
* [x] RPC Implementation
* [x] Read Resource
* [x] Send Transaction
* [x] Chain Interactor
* [x] Smart Contract Parser
* [ ] Mutiple Code Generator
## 0x02 Preparation
> Test Smart Contract Lists:
>
> * hello_blockchain: [0xcd6e69ff3c22db037584fb1650f7ca75df721fb0143690fb33f2f3bd0c1fe5bd](https://explorer.aptoslabs.com/account/0xcd6e69ff3c22db037584fb1650f7ca75df721fb0143690fb33f2f3bd0c1fe5bd/modules)
```elixir
Mix.install([:poison, :jason, {:web3_aptos_ex, "~>1.4.1"}])
```
<!-- livebook:{"output":true} -->
```
Resolving Hex dependencies...
Resolution completed in 0.717s
New:
bcs 0.1.0
binary 0.0.5
certifi 2.9.0
decimal 2.1.1
ecto 3.4.6
ex_struct_translator 0.1.1
hackney 1.18.1
httpoison 1.8.2
idna 6.1.1
jason 1.4.1
json 1.4.1
metrics 1.0.1
mime 2.0.5
mimerl 1.2.0
nimble_parsec 1.3.1
parse_trans 3.3.1
poison 3.1.0
ssl_verify_fun 1.1.7
telemetry 0.4.3
tesla 1.7.0
unicode_util_compat 0.7.0
web3_aptos_ex 1.4.2
* Getting poison (Hex package)
* Getting jason (Hex package)
* Getting web3_aptos_ex (Hex package)
* Getting bcs (Hex package)
* Getting binary (Hex package)
* Getting ex_struct_translator (Hex package)
* Getting hackney (Hex package)
* Getting httpoison (Hex package)
* Getting json (Hex package)
* Getting nimble_parsec (Hex package)
* Getting tesla (Hex package)
* Getting mime (Hex package)
* Getting certifi (Hex package)
* Getting idna (Hex package)
* Getting metrics (Hex package)
* Getting mimerl (Hex package)
* Getting parse_trans (Hex package)
* Getting ssl_verify_fun (Hex package)
* Getting unicode_util_compat (Hex package)
* Getting ecto (Hex package)
* Getting decimal (Hex package)
* Getting telemetry (Hex package)
===> Analyzing applications...
===> Compiling parse_trans
===> Analyzing applications...
===> Compiling mimerl
==> nimble_parsec
Compiling 4 files (.ex)
Generated nimble_parsec app
===> Analyzing applications...
===> Compiling metrics
===> Analyzing applications...
===> Compiling unicode_util_compat
===> Analyzing applications...
===> Compiling idna
===> Analyzing applications...
===> Compiling telemetry
==> binary
Compiling 2 files (.ex)
Generated binary app
==> decimal
Compiling 4 files (.ex)
Generated decimal app
warning: String.strip/1 is deprecated. Use String.trim/1 instead
/Users/rockyrocky/Library/Caches/mix/installs/elixir-1.14.2-erts-12.3.2.13/c4103cbb0a905116c36a4b63e9875c40/deps/poison/mix.exs:4: Poison.Mixfile
==> poison
Compiling 4 files (.ex)
warning: Application.get_env/2 is discouraged in the module body, use Application.compile_env/3 instead
lib/poison/parser.ex:22: Poison.Parser
warning: use Bitwise is deprecated. import Bitwise instead
lib/poison/parser.ex:26: Poison.Parser
warning: use Bitwise is deprecated. import Bitwise instead
lib/poison/encoder.ex:83: Poison.Encoder.BitString
warning: Integer.to_char_list/2 is deprecated. Use Integer.to_charlist/2 instead
lib/poison/encoder.ex:173: Poison.Encoder.BitString.seq/1
Generated poison app
==> jason
Compiling 10 files (.ex)
Generated jason app
==> json
Compiling 13 files (.ex)
warning: use Bitwise is deprecated. import Bitwise instead
lib/json/parser/string.ex:8: JSON.Parser.String
warning: use Bitwise is deprecated. import Bitwise instead
lib/json/parser/unicode.ex:6: JSON.Parser.Unicode
Generated json app
==> ssl_verify_fun
Compiling 7 files (.erl)
Generated ssl_verify_fun app
==> bcs
Compiling 4 files (.ex)
Generated bcs app
===> Analyzing applications...
===> Compiling certifi
===> Analyzing applications...
===> Compiling hackney
==> httpoison
Compiling 3 files (.ex)
Generated httpoison app
==> ecto
Compiling 55 files (.ex)
warning: atom ::: must be written between quotes, as in :"::", to avoid ambiguity
lib/ecto/query/builder.ex:246:8
warning: Decimal.cmp/2 is deprecated. Use compare/2 instead
lib/ecto/changeset.ex:2149: Ecto.Changeset.validate_number/6
warning: Macro.to_string/2 is deprecated. Use Macro.to_string/1 instead
lib/ecto/query/inspect.ex:225: Inspect.Ecto.Query.expr/3
Generated ecto app
==> ex_struct_translator
Compiling 1 file (.ex)
Generated ex_struct_translator app
==> mime
Compiling 1 file (.ex)
Generated mime app
==> tesla
Compiling 34 files (.ex)
Generated tesla app
==> web3_aptos_ex
Compiling 26 files (.ex)
warning: outdented heredoc line. The contents inside the heredoc should be indented at the same level as the closing """. The following is forbidden:
def text do
"""
contents
"""
end
Instead make sure the contents are indented as much as the heredoc closing:
def text do
"""
contents
"""
end
The current heredoc line is indented too little
lib/aptos/smart_contract_parser.ex:60:10
warning: found quoted keyword "type_arguments" but the quotes are not required. Note that keywords are always atoms, even when quoted. Similar to atoms, keywords made exclusively of ASCII letters, numbers, and underscores and not beginning with a number do not require quotes
lib/aptos/rpc.ex:237:8
warning: found quoted keyword "arguments" but the quotes are not required. Note that keywords are always atoms, even when quoted. Similar to atoms, keywords made exclusively of ASCII letters, numbers, and underscores and not beginning with a number do not require quotes
lib/aptos/rpc.ex:238:8
defp cmd__0(rest, acc, stack, context, line, offset) do
cmd__4(rest, [], [{rest, context, line, offset}, acc | stack], context, line, offset)
end
defp cmd__2(rest, acc, [_, previous_acc | stack], context, line, offset) do
cmd__1(rest, acc ++ previous_acc, stack, context, line, offset)
end
defp cmd__3(_, _, [{rest, context, line, offset} | _] = stack, _, _, _) do
cmd__2(rest, [], stack, context, line, offset)
end
defp cmd__4(<<"aptos move", rest::binary>>, acc, stack, context, comb__line, comb__offset) do
cmd__5(rest, ["aptos move"] ++ acc, stack, context, comb__line, comb__offset + 10)
end
defp cmd__4(<<"aptos", rest::binary>>, acc, stack, context, comb__line, comb__offset) do
cmd__5(rest, ["aptos"] ++ acc, stack, context, comb__line, comb__offset + 5)
end
defp cmd__4(rest, acc, stack, context, line, offset) do
cmd__3(rest, acc, stack, context, line, offset)
end
defp cmd__5(rest, acc, stack, context, line, offset) do
cmd__6(rest, [], [acc | stack], context, line, offset)
end
defp cmd__6(rest, acc, stack, context, line, offset) do
cmd__7(rest, [], [acc | stack], context, line, offset)
end
defp cmd__7(<<x0, rest::binary>>, acc, stack, context, comb__line, comb__offset) when x0 === 32 do
cmd__9(rest, acc, stack, context, comb__line, comb__offset + 1)
end
defp cmd__7(rest, acc, stack, context, line, offset) do
cmd__8(rest, acc, stack, context, line, offset)
end
defp cmd__9(rest, acc, stack, context, line, offset) do
cmd__7(rest, acc, stack, context, line, offset)
end
defp cmd__8(rest, user_acc, [acc | stack], context, line, offset) do
_ = user_acc
cmd__10(rest, acc, stack, context, line, offset)
end
defp cmd__10(rest, user_acc, [acc | stack], context, line, offset) do
_ = user_acc
cmd__11(rest, [] ++ acc, stack, context, line, offset)
end
defp cmd__11(rest, acc, [_, previous_acc | stack], context, line, offset) do
cmd__1(rest, acc ++ previous_acc, stack, context, line, offset)
end
defp cmd__1(rest, acc, stack, context, line, offset) do
cmd__15(rest, [], [{rest, context, line, offset}, acc | stack], context, line, offset)
end
defp cmd__13(rest, acc, [_, previous_acc | stack], context, line, offset) do
cmd__12(rest, acc ++ previous_acc, stack, context, line, offset)
end
defp cmd__14(_, _, [{rest, context, line, offset} | _] = stack, _, _, _) do
cmd__13(rest, [], stack, context, line, offset)
end
defp cmd__15(<<"--name", rest::binary>>, acc, stack, context, comb__line, comb__offset) do
cmd__16(rest, ["--name"] ++ acc, stack, context, comb__line, comb__offset + 6)
end
defp cmd__15(rest, acc, stack, context, line, offset) do
cmd__14(rest, acc, stack, context, line, offset)
end
defp cmd__16(rest, acc, stack, context, line, offset) do
cmd__17(rest, [], [acc | stack], context, line, offset)
end
defp cmd__17(rest, acc, stack, context, line, offset) do
cmd__18(rest, [], [acc | stack], context, line, offset)
end
defp cmd__18(<<x0, rest::binary>>, acc, stack, context, comb__line, comb__offset) when x0 === 32 do
cmd__20(rest, acc, stack, context, comb__line, comb__offset + 1)
end
defp cmd__18(rest, acc, stack, context, line, offset) do
cmd__19(rest, acc, stack, context, line, offset)
end
defp cmd__20(rest, acc, stack, context, line, offset) do
cmd__18(rest, acc, stack, context, line, offset)
end
defp cmd__19(rest, user_acc, [acc | stack], context, line, offset) do
_ = user_acc
cmd__21(rest, acc, stack, context, line, offset)
end
defp cmd__21(rest, user_acc, [acc | stack], context, line, offset) do
_ = user_acc
cmd__22(rest, [] ++ acc, stack, context, line, offset)
end
defp cmd__22(rest, acc, stack, context, line, offset) do
cmd__23(rest, [], [acc | stack], context, line, offset)
end
defp cmd__23(<<x0, rest::binary>>, acc, stack, context, comb__line, comb__offset) when x0 === 95 or (x0 >= 48 and x0 <= 57) or (x0 >= 97 and x0 <= 122) or (x0 >= 65 and x0 <= 90) do
cmd__25(rest, [x0] ++ acc, stack, context, comb__line, comb__offset + 1)
end
defp cmd__23(rest, acc, stack, context, line, offset) do
cmd__24(rest, acc, stack, context, line, offset)
end
defp cmd__25(rest, acc, stack, context, line, offset) do
cmd__23(rest, acc, stack, context, line, offset)
end
defp cmd__24(rest, user_acc, [acc | stack], context, line, offset) do
_ = user_acc
cmd__26(rest, [List.to_string(:lists.reverse(user_acc))] ++ acc, stack, context, line, offset)
end
defp cmd__26(rest, acc, [_, previous_acc | stack], context, line, offset) do
cmd__12(rest, acc ++ previous_acc, stack, context, line, offset)
end
defp cmd__12(rest, acc, _stack, context, line, offset) do
{:ok, acc, rest, context, line, offset}
end
warning: variable "params" is unused (if the variable is not meant to be used, prefix it with an underscore)
lib/aptos/cli_parser.ex:38: Web3AptosEx.Aptos.CliParser.handle_aptos/1
warning: variable "params" is unused (if the variable is not meant to be used, prefix it with an underscore)
lib/aptos/cli_parser.ex:42: Web3AptosEx.Aptos.CliParser.handle_aptos_move/1
warning: defp object/2 is private, @doc attribute is always discarded for private functions/macros/types
lib/aptos/smart_contract_parser.ex:6: Web3AptosEx.Aptos.SmartContractParser.object/2
warning: function match_and_emit_tag/5 is unused
lib/aptos/smart_contract_parser.ex:43
warning: :smart_move_leex.string/1 is undefined (module :smart_move_leex is not available or is yet to be defined)
lib/aptos/smart_contract_parser.ex:114: Web3AptosEx.Aptos.SmartContractParser.parse_code/1
warning: :smart_move_yecc.parse/1 is undefined (module :smart_move_yecc is not available or is yet to be defined)
lib/aptos/smart_contract_parser.ex:115: Web3AptosEx.Aptos.SmartContractParser.parse_code/1
Generated web3_aptos_ex app
```
<!-- livebook:{"output":true} -->
```
:ok
```
## 0x03 Installation
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `web3_aptos_ex` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:web3_aptos_ex, "~> 1.4.2"}
]
end
```
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/web3_aptos_ex](https://hexdocs.pm/web3_aptos_ex).
## 0x04 Aptos
**Namespace:** Web3AptosEx.Aptos
<!-- livebook:{"break_markdown":true} -->
### 4.1 Create a Connect
```elixir
import Web3AptosEx.Aptos
alias Web3AptosEx.Aptos
{:ok, client} = Aptos.RPC.connect("https://fullnode.testnet.aptoslabs.com/v1")
client
```
<!-- livebook:{"output":true} -->
```
21:46:26.003 [warn] Description: 'Authenticity is not established by certificate path validation'
Reason: 'Option {verify, verify_peer} and cacertfile/cacerts is missing'
```
<!-- livebook:{"output":true} -->
```
%Web3AptosEx.Aptos.RPC{
endpoint: "https://fullnode.testnet.aptoslabs.com/v1",
client: %Tesla.Client{
fun: nil,
pre: [
{Tesla.Middleware.BaseUrl, :call, ["https://fullnode.testnet.aptoslabs.com/v1"]},
{Tesla.Middleware.JSON, :call, [[engine_opts: [keys: :atoms]]]}
],
post: [],
adapter: nil
},
chain_id: 2
}
```
### 4.2 Create Account
Aptos using the Ed25519 Algorithm for the Account.
```elixir
priv = Web3AptosEx.Crypto.generate_priv()
{:ok, account} = Aptos.Account.from_private_key(priv)
account
```
<!-- livebook:{"output":true} -->
```
#Account<0x508eb8b479f6661348f0180c2e7ef83c548ee89aabadc9232b488308182bb8dd>
```
```elixir
{:ok, res} = Aptos.get_faucet(client, account)
Process.sleep(5000)
{:ok, account_ol} = Aptos.load_account(client, account)
account_ol
# it will works if account is actived(has any APT)
```
<!-- livebook:{"output":true} -->
```
21:46:26.358 [warn] Description: 'Authenticity is not established by certificate path validation'
Reason: 'Option {verify, verify_peer} and cacertfile/cacerts is missing'
```
<!-- livebook:{"output":true} -->
```
#Account<0x508eb8b479f6661348f0180c2e7ef83c548ee89aabadc9232b488308182bb8dd>
```
### 4.3 Read Resource of Acct
#### 4.3.1 Read the resources of the Acct
```elixir
Aptos.RPC.get_resources(client, "0x3")
```
<!-- livebook:{"output":true} -->
```
{:ok,
[
%{
data: %{
authentication_key: "0x0000000000000000000000000000000000000000000000000000000000000003",
coin_register_events: %{counter: "0", guid: %{id: %{addr: "0x3", creation_num: "0"}}},
guid_creation_num: "2",
key_rotation_events: %{counter: "0", guid: %{id: %{addr: "0x3", creation_num: "1"}}},
rotation_capability_offer: %{for: %{vec: []}},
sequence_number: "0",
signer_capability_offer: %{for: %{vec: []}}
},
type: "0x1::account::Account"
},
%{
data: %{
packages: [
%{
deps: [
%{account: "0x1", package_name: "AptosFramework"},
%{account: "0x1", package_name: "AptosStdlib"},
%{account: "0x1", package_name: "MoveStdlib"}
],
extension: %{vec: []},
manifest: "0x1f8b08000000000002ff5d8ebd0ac2301485f7fb14217b638bb3838b9b936ea5486cae529a2621375441faeee64610ed7a7ebe73daa0fb51dfb103a727143b21f721793afb119d8419230ddeb1dca85ad512a0d5c6442442ea809261ab7e361234d72eb798290f1fc7959e98f7d1b60c3118d01974fdc09ca39ff1948c1dae39f212d6f7da7258a9cd94ad8a8a27c502e5dce167e43f5dc6aaef09b9c01b586da59de0000000",
modules: [
%{
extension: %{vec: []},
name: "property_map",
source: "0x1f8b08000000000002ffed1a696fdbc6f2bb7fc5d60f50c93cd657d3c490ede0f9b9426bbcf880ad14cd0b0282925636118a1478c85613fff7ceec41ee2e9714e503ed870a48242f67e79ed999596e6f6f93cb3499d3345f9e057312662420d99c8ec3200aff08f23089493225d7e16c1e510498262919265f689c6d6d6cc3e6d39ccc8239eebaced330be215fe892e409fc2dd1fe16440525f96d909371126761966788325fce297132b6c925413c210b06e82ce8384fd2c362ff9d2b29ccd364114e68464641168e4912ff30be0dc2986434d5f99ca7e12cccc30565083972e4662e781134eec2fc963310c620d08ced97c482284b4856cce7490a9c0255410451197800739893240d6fc2388818c6ad8d5932292260609e27999fa3aafa7db9cf075d91af1b043e454681c149bf3f1a6707fa0ad780b148d3b4b6c605ecf7bf5ed368ea090b3c54409c07063a4d9399af91521e66ccbcc85c854b5adc8e0e45f55179e2671ccce8c10683dcde165fe404cc9d07719ee9ebdb64784bc16beec319282d2e66239a72e309e5725f096232423993944ec04ed563609361426fcac9d9f1effee5d5c5e5e06af8d13f3bbef4af4fff3fe893e2cd6b7244767776760e9a80cf8fcf06fefbc1f92fc35f4bf8bd7d90c21063809a0777b70851f2845e1f44290d264b42efd1c715aa83ff0d3efac75783e39f3ffa83df4faf87fee9b9c67349be5421476fd10dbd1f533ac940479444e8ec2a9d4ab40f67ff1d5c01b193c1e067fffde9d9e950d2d8336894982709cde2ef73cebe1debc590f32f71fda8e0bad4545186f33829e21c70236688b3f1ada997938b0fe74386faec7878f2abffdbf1fb0f03be2ac9bc6e23c3c2786d2ac38f9706919f6c441872a9981a6286a4c42911bd318d08a1411c60d765694f553964db3c494894c4375685a33b332f1d5e5cf8ef2fce7f9134ded6bd1482bf1857a1c6be33b6a625f8db200332f3a54726b0eaf1f81229093f9803aae03fe429c5d393f93b8f813f5889f0748f64186a4fa1a69061ced12755aef7ca47a8f3bec8651aa179318a20fb4f8b98c4f4ce2937806ab31215dfa7a06394aae7154583640d057beaf635ed55024434877ff10d1c24476263bfcf179c1e72e41e94b041066748fe9d23e00f8fec49cb232cc7f7fb610c4c87133f486f8a198d73a735b0dd664a4775d6b83adc165a2b82723d724cb3eb52ab821389692a17a113422d7044e86c9e2f1d132484273b158f77b7219cc64e480e85bd5cc58a720f269323f24a723f4a80dd3b6e478f848ac4aad4f2f455aceed68cab1c325dec5b8b78d720ae1ed5c164e2680ff1d39b15aa9ab600d2ab0101abf5453d82bfca18ad6985bb10eac513c15a0361664708885d9584210c9a2a24ffc6734f2e3d543f2b21d42c8069f5040eda9c6a150199842930112d09563ae5e9a0176c9634e2632de803b80fe07e59a731f047a6183d57fe93461ad3c8df2eb27103c861db5039fddf2819600230e2dd63b18d523c43ac29a1222cd2e4c7f6d5b2a050b3d698056f4365e1b855583d34b00255520edd5f8651eb30f43d853c53002c71fcc0f028492285278d1515530f9658b644046e036dd43827896aaf93955289dca909a7bae75fe6362561450d92b8500030d031b3407797d3ee69c53cbb980e55ad0bbd892d75ed0b466b3677795d6c37b2295d036e11e8abfda9679c935a8a9a4223328148337d943b55dd0c0cdeb3f5580d7a93f9a8d159f17cbca2799182b34611eb3730d96107adf51e78668ab5249d409709bfe0cc8466004c43275ba67e108955f3faa9d86004b6db6a02855fe485550ed82821f3ca99f054f619def5f89747006cf2533a757aaa40fc3ca844f2c8b7c537cbf9b3a8390c1ca67a665e6c217355da6b530f27fb02fa11f2b42848e99cfe122555155c5d4b8a203883f1795aed10cc6268f9b5568a00075546688a5e0464c6c31249a6f2229fee3ba3cd9dfbdd6a40c7c96cba4d19549f24a83953ceed60ce9648b118599e29db9450ec775040b1ff12c217fb4f9615b8ef2ae79bd75d04d50e88e793f4cdeba78b0a027494158237a559d6415e01f912320bd44f965b0ad3d5ce309ded6268007b114b03dea79b1a65e8282f16aeebd7b7cf262fe27db2bc4c86d5f2724e45d72dcf30f35070d579a122b184574e88460a286b1b81da7950222fcf689bb566c9429916d81b04759850da4f4e071c6b3be43e4f75292c1827b9cf561c5bb9d9506f0ad96aa57aad48f9309fe04c469f6ff30284dd2868d767f20a07371e475172470adc8e302530968cdf8b5b041ce540b6c0810daeffc057e7419866a6311822eaab376eeb58e62526c9fcb1694c9c39416fb27aee23a6120dc06212a383031b0de07c205b7795929b2349ab29f21f311f56900bced641de320e6e9e080992cd23a1ee132174259f8f859a5a3fcd45da47a6b53dab46a8fa8e0763aa33258e3d1bb816f6ccd8e0f9b6eabea5a486121e088d329bb8621ae29157addb570fa21a12ab9ddfc7e459cfbc79d22c698d4f952ab05c6fc27da06c498c9558af0c148c74d36c838fc50c59fd34502eba3a5e9a991367d359db9c9891d03d0e51370ce5307d73be4960be1bc1c6f03734a62908c8ef51833ce824f5215ccae2ade13b07b7800d872dd2a0a9d8152bcb2dfc4d84c3e13b47b10306892612876fa878c8b76f35476fd8806dce3ae0d82bac03cf2ace35369485f91a7bac7d6ab9d9cc22cd5e5a567ccb9c666800b41d948f48b6c2674d25eb233564a82262d375edaefaaf4f8021f793385a7eb6bf4483b80e1a80d9040997d81c6bf5d0e8139116c9f360fc05cb68b13029d260144661be5416d171c1689f5b192e7910" <> ...,
source_map: "0x"
},
%{
extension: %{vec: []},
name: "token_event_store",
source: "0x1f8b08000000000002ffdd5a5f6fdb36107fcfa7e05e0a1b706b0c18f6a0a4018675c0fa506c68d2be0a8c45c74424d1a3a8385e91efbe13495994f8477f62bbe982008e45f28e77f7bbdff1a82c974b74bba105ca5852a6046d397ba409295029685a20c1104e1284f304918c0a94931d3c7b2039228f241730618305c29ca09c09447335f82e638fe4424bc45bc18a583e8f22f911cbb5712118acfb7681e0a72c082a44124585e034bf8fa21bf979d919a4f739e1cd43257acd7146768c3f4491141c45df6e48ba5ea03faa6f7fc2de53f21c5884572b56e6a2a38b6d0565b0e3bfe46777b99c82f37d14fd96ef9d2bbb2bb403c0bf5bc2c53ecef0368afed6dfbee2b424971772c99a5302eeb6dda6c7974bfd817e67694a569532949502cb3f5458ea89fa73a95c2143284882761b08e0aa590df15e712ab78d2a2854c2482217433cca9530547d68e67e92f394e80d2e5002d62c9019d6ea67c509864731e08847159a38298a45337c901ce7109208a9c83713589ac4c606ed098049ff84e7a13e2839edb5fd0ba7e7b31936e4b6d51a08db2836c4b433c34f342bb35e5b3fc1bc323b9fb97a5f112a7ffda56daf3df2dccd845b494982e3bc58138e38492bc3462403ceab54e50872f72d553e4b28874d1f849a5e024ef898dfea813ee7541a6f7949105d4bb9b51e60cb055ae3b4b046deb25234bed98a9802a8ef184b43c64f60804aa76496040b2c134021a2306dad310fa207c22088003bf88ae24e9a02ca37f9bd8a2b59e332158df548733285aa274d02f2158d634c677c506b6bda1e951dc771cb03d917117a84558c5fa9c1eb450b6b3ba83869ca76a8dc029e042a983415fc891eab3203794fef3702dd55353b272d87ab0907f9aaf65db5aad4f5753b149d25edb943f9a941617f299a5a808e07cb5355a306919ced712af61e0f7c56a3dfc97abdb7382f33c295e816659b731292b38ce63db3b6784f88af7854feec5369cef1ab346779550e8d50b88c4e289ec70bd0844aaab72d2b89dcef4db5c9af3fcb6d03e574cad92a7cf0ecd47c20eb58f9481dfc812c8c93f995ef7875ed3c4068138609b4c2e09669a4eb30b96e0aeaf0b0689f49f4c9420aee1477a736fb8ce194eff37f8fd3bb55dd90adeb63dc742a7e31fe7ad81238c8bdbd4ead733720c3664663fd00e88400b3ac3b65f85d335ea56b75a4a83a62dd0b4378d7a528795353c9932079211358d7526817db55715d42a1cba9a038a5ff92d86a9067d09e8a08bd51bdefbc49443834ce7e224fb410c59595b8d733351f9a54c52a315b4b49f3f9dc4866e916e8d541ad1c5d3828a03dbb3fb7753b1d4515e32843363d99ae76b60829f2046f88323ba803f405403b44a707cc3ec51d1ef06b70b0824fe6a8d0587ce093dac70e7e1501aef02b9b108491aef7b08a5fbe83637cb247837638540d66a96faaaad3bce4975967fef3fcf2f05d5f8499c79cea5eaf734970e8050f95454edf9677295dcdd40dd55c5257753c8a0384303b1c6f34832d5cc71aabdbeb76797370da3f2574e44590a15222d476d17bffb54d9bd0da77170ed6d4133a3eb5ee349a07ed89dab2f6436ddda21b16c9eba162506fe6b265b27dabfa1eee0b3867bbf83e657738ad4232b048d41a0c15fa5655865afe1d60f296996f40adbdb977a1fad1f6937cd63c9a0f02afd9424e03b18f774680d9d502fa7ac31781dbd30e9f1fe4866136d89d833f2ce87d256624f8bde5ed084950f7a7d312c055b84680bfd5675a9de78be06e77d6e747ba36c646b935f0c322dc711019096ee7d9672ab0f55dbcd543fba0ac76669eaa67f5a1ab41af79b33e0293a6540888e35d808948357b3c22f4764f88885a431011ae7e6308105a0d4d27838ca1dee07ff9fc710c85a98d586750fbaead06c1f9de508c4098c96110e04036eb57c25dbab4ded93839326a29f2f161fbb974c5c403ee77a142d3c420d2ed0e7808ce8f737e3dbcfda8bb6a28dfdb31b80f76e527827ff84dd4e9de269d339102effb4e9952956bed2453beb1f3acfbfcd5a75ae8266848d285efa0a664e0c496516d4d2db69bc5d3559de92f20cf9b3cc33bd323d6a2497de86b4f98e9fde6519bccfabdf4e81c71ddb29e3041fedfefa84f94c4ae1c76fcabc1a9f3d772a47f8ae147ffa4c68d361df4e8f2c4cc3fc9a5ebd5b38beb85c6106671be3999c22a13eeaad46e9cd754a7639531ff5871ce423bf04eec88393aea06ecd8e83f32fc275e75bde07eebf9e23f522f15bd762f0000",
source_map: "0x"
},
%{
extension: %{vec: []},
name: "token",
source: "0x1f8b08000000000002ffed7d6b531b57b6e8f7fc8a1e9f2a46cac818b0e36420765d19e409733178782427772ad569500bfa58526bd41284f8f8bfdfb5df6b3f7bb71036b645a56290baf773bd9f4f9e3c494eaf8a2a1995fdf9304f26d3f2bae8e75532bbca9341391ff7b359518ee1d769725abecbc7d5fa374fe09dddabfce25d399f25e57c9af4f3eb7c584e72f8adbc48e069f2e18c3c9d54b30c8698f693abd96c526d3f79924d6665b50e6f3c115f55dff0b9e957297d6f7b9bbdfefe9b047ee6550e03f5b7b7f3e9b49ceee89f9513b2c0ededf727f970d0498ee89f1f8c87aae2729c9b6f56b36931be946f9ed03fcd37aff38b1999537eca56399866a3fca69cbedbdece2e2ee09c663bfe27e078c633394f8ffcf513ec7d987f08bc342b46391cd168623e439735cbce87b91cf294fc650dc64f12ae14ae66769b8eb2897ce32dfff04d36517ffc9c0de7de61e83f29dd0a2ca19ce6fc4c9e3ce1ff24bbe598dce9ac129fd37f2fc8a7c9e9d1ffed1da66fbaff9dbe393bedbe3ae8a5fb877bdbc9fcf9b3e445b2b1633d7976bcef7a72d37ef2f8e8d7eec1e9afaea7b7eca7f77a27bbc7fb6f4ff78f0e5d6f3cb5df787b7cf4b677ec9ee059e0f19fbb07673dd74bdfede083d93d3a38e8edd2f5d4ac4d3b25f45acc51a1c73d77b0a5ad8a3c84de39ecbee9a507bdc37f9cfe2487dffa61c778e1f0f569e49364c9fa43df6d6e497892f098bccb6f130a6bfda41803991964f3e12ce5005d0095822167d3723804c44d6eaecae4221b27e7f3e998922f0ab1eb6250f2c945399de6d5a41cf7c90b0231926b02f70910c157bb2749954f8b6c58fc09739e97e5701d2dfdd5d9f1213db757bfa6bbc7bdeee9d1f176c208c48ff31f5ec236ce1f3128703cf968c733d2d12f87bd9871e8738fea01d43394f6d8293cf7c842e01e21af95fe21610ffc2893abac4aceb36136be00da30ee93d31e97b3e41cce6e5cccf8a9a1f5f5ba07b0f7bd5fd39fba27e9abee41f770b787a019cf3025e73ffeeb0cc6bd85b78743d802e13bc08080adcc0887e274168faf40f4243d3c3a4ddf9ebd3ad83ff9a9879140ceb2cb563b28c8cad50c005817d33c8303fb6bcd1cee29b6f48de0a1b3210cdcbf4df23f8a8a53457b507146bdffde3f393d4184488edafbe322cffb158760313aac7694fd518cb261329e8fcee194ca01bba7147876a6cd4620b097fe727476b007f3ecf67a7ba94e11f6df9cbd41444d4ebd3faee68341715100d5e740c001008fbf7f7872f6faf5feee7eeff0d4bce7efec1b18e5d3cb9c61e84dc946ad929b627695f48bc1004041ce55f4f56980a6eeefa59c97f48eff2167796e1d97a20009390e7956d97058dee850fa661f96ad1d8ee456f85cbe47731c968ccc5c6493ecbc1816b35b3ce0e11145dc74b7fbb6fb6aff60fff45731c60f1858c8e2f6c8dafc70c29956f7b4eb8193bf3b0724a73c999f0f8bea4adf2a1acf8d2f1be6782784fc825c9753eca42bb4073c01fad6f38ce840c16a0227c62f675602ca27d988a05d32cc003208bac347c5ace21f3be67b0b879a76df1c9dc1cd1d7401108ed3a3e3b4f7afb3ee015c1ebf3ff6bd624306a20e8a7cd827549fc2e49c4a5478aad7fb3d8008b2294958f9484f3548009a359f5d9553ca32603b64a8596ec00325ba3d07446c3e334f9caea7402c8cb1406340b6c5fdc314dd801c1323dd5945e4f2a24fae0f64e5c784911653a021c96c9a8d2bc0373cf2d9091c25d9f3d1db5332fadefe315089f4f4b87b78f29ab0293ec373fb560906f7a7d94db2c1968d87fd65fff4a7bde3ee2fe9ffeb1d1fc941bef781462680e32a83458f87b794f56c3ae081ca1cb05c0a11da25fda0a3eba800f8f2a22b25018ecbf9bb9fb88f415227d0332bcb64588e2f7d3c830844a74747e9c1d1e13f24cff8ce1817b6111c508a56d648cf8d9140b4f20d42a42eeb7dc71df4f34959d15b60f04849f386ebf08f40667d7b7402b8c8a0905c33bd6203f7b67eb067a1f473834de1229e35235a844f60321997a072727e9b9437631dbca90c05177d4860464d23b9ee46cca85c5cb038ec5168644c068f73c0c96ba01694045554b966004fe5d9ec62661d569ecc27c0c788507a4b74337d7636ebd9db3d42638e7b80c33f031713129f5c834601c9eaf4ab157b75b04876197c9e9fba3ff75c77f214d3c5e3f2361b826c5d8c41ba2e80ce0e28410351259f92d3239361724fbeece7e312f0d43c5cc1f785a6777806bc9f1ef71e400ba02e13c4f9229e391631c96ef35c08779499d18d5adc4cccf0b6fb6baf977677772983d93bea31f192b25e399126d928ba20ee52491df311f0848a5e22de71359f4c86b7ae8d1a82c7d3e71654bec52a90d813a1f0a36c767165df1c07857dd808db13656bddd35da9803d258440cef28ba0e58a62ca29aeb26bb08d28b1d0a60b9a3c2849bf22af26dc60ea206706ed0c04dafc8f0930abcac94b605347afe152de028f5282b349b2a59607003715880748a4dba7f0045253929804dad7c969f770af7bac54ff0d87fd83484ae4dac1b234bf98cd613a8adb57e5902a9c4cd4c56fb107f9a5121e47593d377b919fa2bfcdbeddef77e4874fb83acbd156c8fdd57a724478a534f85ce7d38a8024685b5433a637977175f7bcb894a0b8b92ec76663d25dea13a2b32460472907d5cb909a2d9ebdb982edb896d151520d56e3b329d3072ac202e1141c9a3e882d52beed2437442425c0c8ceab9839e69fa1cb27b62f2e98551d3882717e63af8fe89815b5145239ce3021901f73e1db9a1d8d3ef64141dfe5b004650954d8e23fc4bc00d46d5600c5a78a5a8664240c04fb7d05061d00c8c96d27e9c3" <> ...,
source_map: "0x"
},
%{
extension: %{vec: []},
name: "token_coin_swap",
source: "0x1f8b08000000000002ffcd575f6fdb36107fcfa7e0d3da0246b23f5d37a85d81cc515ba3891d24ceba3d11b444c74464d220a9a45e91efbee3919468496e83210be617593cdeffbbdf9d8e8e8ec809df685e30cb4bb256655df103ff206c6395a156dd709965f8a08512929a3bb6215f0e08fc6ac389b1659619ab85bcceb24b7cbede2572ad956ecfbc5ca458b6a87896cddd63f8c276c3a9904b0597e0ef04fe75ef2d355bf33ba56f40d12d9736cb72f7f8c064d9179a7a93655fe6ee3922f89894f7af0ff0fad1517890dc596e0ee369781e7906c22acd59b9259530103d24164a1a4bf2f9ec633ea5c7a717f9f1c95ff4747239cf4f3252bf7a497e233fbceeca71fc10352215a994bce69af0cf7064fa129da4c9f43d9dcee634ff135ea2d01f7b42850179960849b829b4baeb0b734226539a5f8e2f669fa2a09f7a820a269da00587f2b8852251b5256a19a4c2f152694eec8a83edc54dbd2156ac795fd9f878eaf49dcdfec8e9ec6a4e67ef8262fa7bfe6e7691d3d3d9f8e3d5399d4fcef268cbcb9e2d8b7a4b365a149c948a1bf9cc9235b3c5aa8920d2facacfc0cdf38bc938479fcf8ee7e30f51c7cf833ad85ad5d2ee51e28903e93e9b5d4de77d15af121553882497aabe5e11d74bc42ad487f5984ac4044f6757ef3fd0f16c328da27e4944f5fb36e13fc9cf2ff2f131941d84fce4eab489e9af5d7fc760c6a5eb6810a674690823d8e0ccdc10482dbe6c9cdb1e014264ee845d11c7eabad2bf31b21652ac591532b4813a6efd0280a80bbbabf2cd66c5a455eb46d05bb26206ae42458d48a9558419f74bd5a333a386047a29eaa4a033b4787be33e71d85569c8229430ab2a2fd6ec7a8a069484594f25ea4e72fd0c2253144de6537f4ebd48b3c79f1bbe4dfc0033dc01b4a7eb19af4094bb060074915b56d53c5e030f4354c16ccbf435b7a17e40cb61233bf866328288fa26e0daa813f6c6bcb7a32e2b450805010986be499dc4f384cfd9bc9fc9a94b39ee3bc5977b1059a9aa4ce2e1fe42f05be071f5556a7607a9809ad24c9a25cc9400b96926a2bc5845ddfac9fcb5519a0dc8a8a81a0083bc3b0023ba063300ea4648c10a880639184c9217f0d01d24481b84bbd3922f595dd936a3df933567127b2a95dd0ac6d43ab94c6e1b38c52ca185144da68617664f9d63ec5d0076020c1d0a8ded6c8d5507f003fa4468d4bc353f0dea8ea05e3dfbbef49eef293ccfbb5b0203fd8385821a5ceb8f8633484599c579dda6f1ebb0d039ff5a103d840263bb7890b878ecb5bfa9f27f67bc27c118e03a23ac2c353766f410dc4343f753bee5c2a65e54a220cb5ae2a0a30d04b8e5a30589e78d540fad140b76c052daf311492f32b250aa4a62c1164ac31874bb559609097d214a0aa056af2186cffbb3eb45b7bec7d81fd837111a9a718ac30b0752c012bf9d7500d6a60d1ce1dd3b74d80d0eff5c00ae5f73bffd821cefe86084f04a08d077465cc39f51873a98b06f85b6804d132acad0401abca3aa8a1756288039bf872744094bf2c0f1068a956bbba5b75c1be41c32ab67f28bc7cce6bccd0226cba498b493b73433205c6f313f8e2718ea92637646dcbeea1d48ceff2bc4487310864533b4d8e08d61307bfc244da4b0c0f4773af9e22ae552c4d266422e971a5808ad40b6e0666049f233989647363dd890989e4cea413b11bec3547b0213cfeb1490042c91f1fbaab30925cb8fdb8522fac1db62db6e133d082bf9461911bbc4aae8d9839be32be3cbd34c6fb57ab2d23cd7e2163e839ca3d89a588fcd5c880bbe86bd9cc5c4c7151f47468b3ea1e19bb2884222ba808c103998ab966bc9aae11022863c684426b40402e2e0f4d0f888b1fa3414966e5b1c9289259273ff3188a5e0262babed4a69e8916e75ed0fd3e314d8530466cc64c1ab41605b8acfee6bb0fdea4f5c2f906d2fb83d5e7ffd3733f8fee01fc8dd27dd02140000",
source_map: "0x"
},
%{
extension: %{vec: []},
name: "token_transfers",
source: "0x1f8b08000000000002ffd5596d6fdb3610fe9e5fc17a802701422d752f2894261850a46831a019d6001b1004822cd18e1059f448caa957e4bf8f6f92488a929dc4493a7f882292c73bde3df7f048cd663370715d10b042795d42b0c66853e490007a0dc102d5559ed20255ec5f0c284e2bb2801817d512a005b84037b022474a325d534412cadbe2583c924680806f4780fd6a0201a1791c936259417c6c35523e711c7f114fab9369459a8054267a683a2f611c7ffb02cb45002ef8db9d3d50b7aa1bcadfd4e353de9359e074056f11be89e334cb9827e8c808b881156d673ee36f1fd32a17a608a9d94c3dc0195f0979ddb4aae74cdac1dccafc05720449f52305f06b41a81891a18a50707671fefbd9e7e4fcc387b33f93cfe717c9d9df9fbe5cc4a0fef567700222a58b39b2ce28f803563973e4fb322d56045ca704dcc0ad8a04ffad657f928901b174dd3b61c639b7e253ae9c731ab432c2bc44ac964968ebd4e444ab2693a55506cb6487e87b31ca3d013770449277eb3277861bf405092f6468bd0d408ed13a606310869a4f284ad23cc731e07f212181d6c3115de4710398715dc21ea16e541153b1bf2efe4b571c8922e28306d8ae7c2933dab83ca3018bba024555d0222d8b7f6162f190a7323906534941be66ca0a6db880d736083d5220301acdccfa66f4b9324b5154056f9de9e5f9416f0a335b1ab3f914b231b976a75db342c794ce3cdc31732f2bc7e637d274d7c45dd20e4c79d7bef97680330c53da0457aea7c8bd5eeef6f1e3c7261d74a11b68d6201a588d72ea23d35c65e4ba9e974506d8eaf056582c8d24192ed6b40318613881cc6089c54e0186192c36d0454362e9c8d983ca12667cb38e81dc42bbbe8a6d54fd56b6d7af21a6db84a92242aecd26678af92ca8ffd405533b980125a4ad6bd88ea4365c235e459ee0f4d6530b0934bb036167d0b3cb3f36f71f6f2a1d17b48eea421d28b3958c198f3612fd104cef1183fbd0d29e3e9366089c31b7495b58dd213533887b7280e6896201bc57a23e20ef8c994f3d6d32dfb7c03cc28d4a458768554e34369aac064e8c79a7ab9a823962b5cd6db22cd13c2d13d63266d96b73be6307869ad4662e71a77c3ffebe639e0e88b705bdce19fae43c5e03a301f0b46e56fccd6a309a1615f14ccb03cbda9ecf95385bf50e49f5aea9bf03b024d09a8f2f2c2734691727e757de676edf65e0719fcae27805f1127aedbc0e5b343ca87a17ae0a2ac9bdbf113d161efa3e6572af5d65f53760bdaa6831e218a5c2deeb9130b0f6a3eed5492e1dd9cb8dd026fb8e506caa6938e8a5c8fe3be075e1326fdae5b39d9a837c2e251d5e9eeeede6013edfc32d29216c41afbc311ef68381639b455507a3d78330ab630b6a5ceb3bd9b671c53db93200e264cfca44441371dfe00d78cbc5eca4633f0c79fdbe3ff3f139649a77785e42457e89ecf1a6528b26a646e6708d48a146dbdb101fbf8b29f5faf71191d66b6e07496a47b071921c0df7f311a77e42f9ff14cbdf037f6a9e1b2b8fcd00f0dba8afac00040b8c5600d5d8262176606393d01a576c06b04c994578db63605df75314d64f56431faad2dc671b9055cd73ef05fb96dacfc2a3bb68d4d8f3f7e1d0dee5c463fde4b82271b1aa7dbff6c205e80f971412da30070bc36fe1d72800e89625807c7be35fd959cb45926ad18ab5c42ae59ad7fb739b9e3fdeb4a5b3c8b78e93aa67245f1b610b6dc2be313131404fcf81fbfc9680d53bab3f70225cd9a9e8df3db42bea06e927c8a85fd58a8181b16083468e6c15a302960a83f87769da1334a1428d7a8de4eb4f03208279c17729e2f5f75d9bfbe5ec03ed91d97e30e4bd392cf2c29dd00b1f8fbdd0065fab3edaa93e7abcfaa8513f0efe70149a4e91c829d23f45c8fd817136c7b7d8bc47a2a4611c9c9c8070380bc31dc9717f1b54c42d13a26113a2a731211a30c1c92de1683406ac76867c4843b41f7d3d404459350e2b17d725a82ab75703270f9d3a5afa6a6a57fd5ad76f8b538d887adfb0d587607988b02f52bbca3ee1853dcf652556d3c55b6f3ef908cb1205e02f84cb7c62918026ccaa19f1713e219052fe4dfe046c5817c2efe60895a7978b94dd1d06407f5c3d861a1cd86b3250878179b8e9ec35abb3267e66a3e919b3d372d27bed08673a6c54ec9ad235896733b1fcd739dcd8e3a341936c7f1bf59863537a407cda07fb8eaa074b5cf9c2455a9734615ff149379584d8e9a5b5cc94d234bb616bb3d75fd52b16b8842176e20f28d830133a05ea51bf3d3dbd9c4fa2701280f9e497c9802cddaee16eeb8a8ac225c40ef3da9eabe3014049dfdab70307819448ec164de26d079ac686ba6a7857db7d013a92861692c3d06c085ddf308751cd7f3ae8dc3d1c2dee1e8185dea16528a2eafee3614b3d7094c3deb7e7bba3ff00d0ef041f2a250000",
source_map: "0x"
}
],
name: "AptosToken",
source_digest: "DCC9F79C2AB5C92AD5BBA327A5749793DCC604A11E381F3B0D8F59CCF384075F",
upgrade_number: "17",
upgrade_policy: %{policy: 1}
}
]
},
type: "0x1::code::PackageRegistry"
}
]}
```
#### 4.3.2 Read resource by resource_type
```elixir
Web3AptosEx.Aptos.RPC.get_resource(client, "0x3", "0x1::account::Account")
```
<!-- livebook:{"output":true} -->
```
{:ok,
%{
data: %{
authentication_key: "0x0000000000000000000000000000000000000000000000000000000000000003",
coin_register_events: %{counter: "0", guid: %{id: %{addr: "0x3", creation_num: "0"}}},
guid_creation_num: "2",
key_rotation_events: %{counter: "0", guid: %{id: %{addr: "0x3", creation_num: "1"}}},
rotation_capability_offer: %{for: %{vec: []}},
sequence_number: "0",
signer_capability_offer: %{for: %{vec: []}}
},
type: "0x1::account::Account"
}}
```
#### 4.3.2 Read the item in Table
💡 You could get handle in Explorer:
> https://explorer.aptoslabs.com/account/0x2df41622c0c1baabaa73b2c24360d205e23e803959ebbcb0e5b80462165893ed/resources
```elixir
Web3AptosEx.Aptos.RPC.get_table_item(
client,
"0xe30b2ff6a515aa04729522512d50147d5cdd52ee3741c26ff1b97306b0b2b148",
"0x1::string::String",
"0x65f4a0954aa6e68d2381ff98b7676df2fe57beee3ca37a4a8a57fa621c1db872::addr_info::AddrInfo",
"0x73c7448760517E3E6e416b2c130E3c6dB2026A1d"
)
```
<!-- livebook:{"output":true} -->
```
{:ok,
%{
addr: "0x73c7448760517E3E6e416b2c130E3c6dB2026A1d",
addr_type: "0",
chains: ["ethereum"],
created_at: "1673525423",
description: "A Test Addr",
expired_at: "1705061423",
id: "1",
msg: "50789538.1.nonce_geek",
pubkey: "",
signature: "0x",
updated_at: "0"
}}
```
### 4.4 Send Tx
```elixir
{:ok, f} = ~a"0x1::coin::transfer<CoinType>(address, u64)"
payload = Aptos.call_function(f, ["0x1::aptos_coin::AptosCoin"], [account_ol.address, 100])
Aptos.submit_txn_with_auto_acct_updating(client, account_ol, payload)
```
<!-- livebook:{"output":true} -->
```
21:48:50.442 [warn] Description: 'Authenticity is not established by certificate path validation'
Reason: 'Option {verify, verify_peer} and cacertfile/cacerts is missing'
```
<!-- livebook:{"output":true} -->
```
{:ok,
%{
expiration_timestamp_secs: "1692193790",
gas_unit_price: "1000",
hash: "0xe574135a727ae366740e08247dcbd925c05cc931212dda5ed241bc5633703ed6",
max_gas_amount: "2000",
payload: %{
arguments: ["0x508eb8b479f6661348f0180c2e7ef83c548ee89aabadc9232b488308182bb8dd", "100"],
function: "0x1::coin::transfer",
type: "entry_function_payload",
type_arguments: ["0x1::aptos_coin::AptosCoin"]
},
sender: "0x508eb8b479f6661348f0180c2e7ef83c548ee89aabadc9232b488308182bb8dd",
sequence_number: "0",
signature: %{
public_key: "0xce70449765f180af68a038adf1c9893e72897ef579b7b138855fe8daaa4be438",
signature: "0xea8cd7270fb59b3e55332dc2f6f06cc6fb53bf361abda011f3235c40b715dd592c9cfc84c12057f14fa5be1cb0143d0924633db36f6ce45b11398875044de20a",
type: "ed25519_signature"
}
}}
```
### 4.5 Smart Contract Code Parser
Parse the smart contract code, it is the basis for generating call-codes for mutiple langugage, and the embedding for the smart contract to vector dataset!
> https://ai.movedid.build/
```erlang
# TODO: make it run in livebook
payload = " module hello_blockchain::message {\n use std::error;\n use std::signer;\n use std::string;\n use aptos_framework::account;\n use aptos_framework::event;\n\n //:!:>resource\n struct MessageHolder has key {\n message: string::String,\n message_change_events: event::EventHandle<MessageChangeEvent>,\n }\n //<:!:resource\n\n struct MessageChangeEvent has drop, store {\n from_message: string::String,\n to_message: string::String,\n }\n\n /// There is no message present\n const ENO_MESSAGE: u64 = 0;\n\n #[view]\n public fun get_message(addr: address): string::String acquires MessageHolder {\n assert!(exists<MessageHolder>(addr), error::not_found(ENO_MESSAGE));\n borrow_global<MessageHolder>(addr).message\n }\n\n public entry fun set_message(account: signer, message: string::String)\n acquires MessageHolder {\n let account_addr = signer::address_of(&account);\n if (!exists<MessageHolder>(account_addr)) {\n move_to(&account, MessageHolder {\n message,\n message_change_events: account::new_event_handle<MessageChangeEvent>(&account),\n })\n } else {\n let old_message_holder = borrow_global_mut<MessageHolder>(account_addr);\n let from_message = old_message_holder.message;\n event::emit_event(&mut old_message_holder.message_change_events, MessageChangeEvent {\n from_message,\n to_message: copy message,\n });\n old_message_holder.message = message;\n }\n }\n\n #[test(account = @0x1)]\n public entry fun sender_can_set_message(account: signer) acquires MessageHolder {\n let addr = signer::address_of(&account);\n aptos_framework::account::create_account_for_test(addr);\n set_message(account, string::utf8(b\"Hello, Blockchain\"));\n\n assert!(\n get_message(addr) == string::utf8(b\"Hello, Blockchain\"),\n ENO_MESSAGE\n );\n }\n }"
{:ok, tokens, _} = :smart_move_leex.string(String.to_charlist(payload))
:smart_move_yecc.parse(tokens)
```
## 0x06 Contributing
Bug report or pull request are welcome.
## 0x07 Make a pull request
1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request
Please write unit test with your code if necessary.
## 0x08 License
web3_aptos_ex is available as open source under the terms of the [MIT License](./LICENSE.md).
## 0x09 Distributed Rules
<!-- distributed_rules -->
Contributors:
```
pool, 20%
https://github.com/leeduckgo, 30%
https://github.com/zven21, 50%
```
<!-- / distributed_rules -->