plugins
.
Wallet source code:
This feature allows developers to implement complex logic that works in tandem with a user’s wallet. For example, a DApp may require a user to pay a small amount of coins every day to use certain features. In this case, the user would need to install the plugin on their wallet by signing a transaction. The plugin would then send coins to the destination address daily when requested by an external message.
Official code hashes
Contract version | Hash |
---|---|
V4 R1 | 64dd54805522c5be8a9db59cea0105ccf0d08786ca79beb8cb79e880a8d7322d |
V4 R2 | feb5ff6820e2ff0d9483e7e0d62c817d846789fb4ae580c878866d959dabd5c0 |
Plugins
Plugins are essentially other smart contracts on TON that developers are free to implement as they wish. In relation to the wallet, they are simply addresses of smart contracts stored in a dictionary in the wallet’s persistent memory. These plugins are allowed to request funds and remove themselves from the “allowed list” by sending internal messages to the wallet.Persistent memory layout
- seqno: 32-bit long sequence number.
- subwallet_id: 32-bit long subwallet_id.
- public-key: 256-bit long public key.
- plugins: dictionary containing plugins (may be empty)
Receiving internal messages
All previous versions of wallets had a straightforward implementation for receiving internal messages. They simply accepted incoming funds from any sender, ignoring the internal message body if present, or in other words, they had an emptyrecv_internal
method. However, as mentioned earlier, the fourth version of the wallet introduces two additional available operations. Let’s take a look at the internal message body layout:
- opcode?: 32-bit long operation code. This is an optional field. Any message containing less than 32 bits in the message body, an incorrect opcode, or a sender address that isn’t registered as a plugin will be considered a simple transfer, similar to previous wallet versions.
- query-id: 64-bit long integer. This field has no effect on the smart contract’s behavior; it is used to track chains of messages between contracts.
- opcode = 0x706c7567, request funds operation code.
- Toncoin: VARUINT16 amount of requested Toncoin.
- extra_currencies: dictionary containing the amount of requested extra currencies (may be empty).
- opcode = 0x64737472, request removal of plugin-sender from the “allowed list”.
External message body layout
- signature: 512-bit long Ed25519 signature.
- subwallet_id: 32-bit long subwallet ID.
- valid-until: 32-bit long Unix time integer.
- msg-seqno: 32-bit long sequence number.
- opcode: 32-bit long operation code.
- opcode = 0x0, simple send.
- (0-4) mode: up to four 8-bit integers defining the sending mode for each message.
- (0-4) messages: up to four references to cells containing messages.
- opcode = 0x1, deploy and install plugin.
- workchain: 8-bit long integer.
- balance: VARUINT16 Toncoin amount of initial balance.
- state_init: cell reference containing plugin initial state.
- body: cell reference containing body.
- opcode = 0x2/0x3, install plugin/remove plugin.
- wc_n_address: 8-bit long compact workchain ID specific to this layout + 256-bit long plugin address.
- balance: VARUINT16 Toncoin amount of initial balance.
- query-id: 64-bit long integer.
0x0
opcode, similar to previous versions. The 0x2
and 0x3
operations allow manipulation of the plugin dictionary. Note that in the case of 0x2
, you need to deploy the plugin with that address yourself. In contrast, the 0x1
opcode also handles the deployment process with the state_init
field.
Exit codes
Exit code | Description |
---|---|
33 | seqno check failed, replay protection triggered |
34 | subwallet_id does not match the stored one |
35 | Ed25519 signature check failed |
36 | valid_until check failed, transaction confirmation attempted too late |
39 | Plugins dictionary manipulation failed (0x1-0x3 recv_external opcodes) |
80 | Not enough funds for the funds request |
0 | Standard successful execution exit code. |
Get methods
int seqno()
returns current stored seqno.int get_public_key()
returns current stored public key.int get_subwallet_id()
returns current subwallet ID.int is_plugin_installed(int wc, int addr_hash)
checks if plugin with defined workchain_id and address hash is installed.tuple get_plugin_list()
returns list of plugins.