Mintlayer-ERC20 bridge
The purpose of the bridge is to transfer fungible tokens between Mintlayer and Ethereum chains.
API server endpoints
-
api/v1/bridge-request- submit a bridge request.E.g. (e2m):
curl -H 'Content-type: application/json' \
--data '{
"source_chain":"Ethereum-XYZ",
"destination_chain":"Mintlayer",
"asset":"FOO",
"amount":"100.00",
"receiver_address":"tmt1q94w2g3vwvw74swj3gx4kaf5qelapmdhyyyxe3ef",
"deposit_transactions":[{
"raw_transaction":"02f9...bd03"
}]
}' \
-X POST https://SERVER_URL/api/v1/bridge-requestOr (m2e):
curl -H 'Content-type: application/json' \
--data '{
"source_chain":"Mintlayer",
"destination_chain":"Ethereum-XYZ",
"asset":"FOO",
"amount":"100.00",
"receiver_address":"0x6CFF507AeA2FE77a508E13DD4C2dF495780871D5",
"deposit_transactions":[{
"intent":"e901...a9be",
"raw_transaction":"0100...5250"
}]
}' \
-X POST https://SERVER_URL/api/v1/bridge-requestAlternatively, instead of passing the complete deposit transaction you can specify its hash.
E.g. (e2m):
curl -H 'Content-type: application/json' \
--data '{
"source_chain":"Ethereum-XYZ",
"destination_chain":"Mintlayer",
"asset":"FOO",
"amount":"100.00",
"receiver_address":"tmt1q94w2g3vwvw74swj3gx4kaf5qelapmdhyyyxe3ef",
"deposit_transactions":[{
"transaction_hash":"a76b...cb84"
}]
}' \
-X POST https://SERVER_URL/api/v1/bridge-requestSame for m2e.
Example response:
{
"bridge_request_uuid": "aac4d30d-91c7-4e2e-94d9-00bb3709771e",
"deposit_transaction_uuids": ["25c43ed1-d2eb-4a1a-b546-16c67d6303af"]
}Note:
deposit_transaction_uuidswill have the same order asdeposit_transactionsin the request. -
api/v1/fees- return the contents of thefeestable.E.g.:
curl -X GET https://SERVER_URL/api/v1/feesExample response:
{"bar":{"fixed_fee":"5","percentage_fee":"0.1%"},"foo":{"fixed_fee":"10","percentage_fee":"1%"}}. -
api/v1/subscribe- open a websocket to receive notifications about status changes of bridge requests as well as deposit and withdrawal transactions.Example messages for a successful bridge request:
{"event_name":"bridge_request_status_updated","uuid":"93bc6941-ebc5-4eae-8226-de7a606defcf","status":"pending"}
{"event_name":"deposit_transaction_status_updated","uuid":"8d6f7745-6133-4bc6-a230-dc577d1ab626","status":"not_yet_submitted"}
{"event_name":"deposit_transaction_status_updated","uuid":"8d6f7745-6133-4bc6-a230-dc577d1ab626","status":"submitted"}
{"event_name":"deposit_transaction_status_updated","uuid":"8d6f7745-6133-4bc6-a230-dc577d1ab626","status":"confirmed_by_network"}
{"event_name":"withdrawal_transaction_status_updated","uuid":"a78113ac-5984-47fb-9405-785dc38e6aae","status":"master_signed"}
{"event_name":"bridge_request_status_updated","uuid":"93bc6941-ebc5-4eae-8226-de7a606defcf","status":"processed_by_master"}
{"event_name":"withdrawal_transaction_status_updated","uuid":"a78113ac-5984-47fb-9405-785dc38e6aae","status":"submitted_to_network"}
{"event_name":"withdrawal_transaction_status_updated","uuid":"a78113ac-5984-47fb-9405-785dc38e6aae","status":"confirmed_by_network"}
{"event_name":"bridge_request_status_updated","uuid":"93bc6941-ebc5-4eae-8226-de7a606defcf","status":"completed"}Note: deposit transaction status change to "submitted" won't happen if the transaction has been submitted to the network by other means (i.e. outside the bridge); in this case the status will go from "not_yet_submitted" directly to "confirmed_by_network".
Other possible statuses are:
- for bridge requests: "failed" - the request has failed, "manual" - the request requires manual handling;
- for deposit transactions: "confirmation_failed" - the transaction could not be confirmed, "invalid" - the transaction is invalid;
- for withdrawal transactions: "failed_revalidation" - the cosigner determined that the withdrawal transaction is invalid (note that this is not a normal situation), "failed_submission" - the cosigner failed to submit the withdrawal transaction to the network.
-
api/v1/bridge-request/{uuid}- obtain some information about a bridge request given its uuid.E.g.:
curl https://SERVER_URL/api/v1/bridge-request/034d5ce2-70f4-4089-a330-97d8d8f23775Example response:
{
"uuid":"034d5ce2-70f4-4089-a330-97d8d8f23775",
"source_chain":"mintlayer",
"destination_chain":"ethereum-xyz",
"asset":"foo",
"amount":"100",
"amount_after_fees":"89.1",
"sender_addresses":[
"tmt1q94w2g3vwvw74swj3gx4kaf5qelapmdhyyyxe3ef"
],
"receiver_address":"0x6CFF507AeA2FE77a508E13DD4C2dF495780871D5",
"status":"completed",
"created_at":"2025-03-10 16:28:58.753664 +00:00:00",
"updated_at":"2025-03-10 16:33:43.879247 +00:00:00",
"deposit_transactions":[
{
"uuid":"1bcea941-2761-4655-a875-fe01c00120c6",
"transaction_hash":"ef366c9129f6d36b7b8a7adde13a061351ea20d16b857bacab28a0ed6f8ead2d",
"status":"confirmed_by_network",
"created_at":"2025-03-10 16:28:58.753664 +00:00:00",
"updated_at":"2025-03-10 16:29:10.875763 +00:00:00"
}
],
"withdrawal_transaction":{
"uuid":"52d4bfdf-8a7c-4ea2-af54-5f287f747ffc",
"destination_chain":"ethereum-xyz",
"transaction_hash":"98267a71c2f40911da3aa71ee9beb7764729159d1c70510c42fa604c05dc2894",
"status":"confirmed_by_network",
"created_at":"2025-03-10 16:29:11.023903 +00:00:00",
"updated_at":"2025-03-10 16:33:43.879247 +00:00:00",
"bridge_request_uuids":[
"034d5ce2-70f4-4089-a330-97d8d8f23775"
]
}
}Note:
- The order of deposit transactions is unspecified in this case.
amount_after_feesandwithdrawal_transactionwill benullandsender_addresseswill be empty if the request has not been handled by the master yet.- The returned data contains the full info about the withdrawal transaction that handles the
bridge request (if any) instead of just a uuid. Though this is somewhat redundant (e.g. the uuid
of the bridge request is also present in the
bridge_request_uuidsfield ofwithdrawal_transaction), it's supposed to help reduce the number of requests that the UI has to make.
-
api/v1/deposit-transaction/{uuid}- obtain some information about a deposit transaction given its uuid.E.g.:
curl https://SERVER_URL/api/v1/deposit-transaction/1bcea941-2761-4655-a875-fe01c00120c6Example response:
{
"uuid":"1bcea941-2761-4655-a875-fe01c00120c6",
"transaction_hash":"ef366c9129f6d36b7b8a7adde13a061351ea20d16b857bacab28a0ed6f8ead2d",
"status":"confirmed_by_network",
"created_at":"2025-03-10 16:28:58.753664 +00:00:00",
"updated_at":"2025-03-10 16:29:10.875763 +00:00:00"
} -
api/v1/withdrawal-transaction/{uuid}- obtain some information about a withdrawal transaction given its uuid.E.g.:
curl https://SERVER_URL/api/v1/withdrawal-transaction/52d4bfdf-8a7c-4ea2-af54-5f287f747ffcExample response:
{
"uuid":"52d4bfdf-8a7c-4ea2-af54-5f287f747ffc",
"destination_chain":"ethereum-xyz",
"transaction_hash":"98267a71c2f40911da3aa71ee9beb7764729159d1c70510c42fa604c05dc2894",
"status":"confirmed_by_network",
"created_at":"2025-03-10 16:29:11.023903 +00:00:00",
"updated_at":"2025-03-10 16:33:43.879247 +00:00:00",
"bridge_request_uuids":[
"034d5ce2-70f4-4089-a330-97d8d8f23775"
]
}Note: in m2e the actual withdrawal transaction (i.e. the one that is sent to the network) is created by the cosigner. So, the returned
transaction_hashwill be null if the withdrawal transaction has not been handled by the cosigner yet.
In e2m, on the other hand, the actual transaction is created by the master, so in this casetransaction_hashwill be known right away. -
api/v1/agents-config- obtain agents' configuration values.E.g.:
curl https://SERVER_URL/api/v1/agents-configExample response:
{
"network_type":"testnet",
"ml_tokens":{
"bar":"tmltk1lht3lwdzkdydwr7qk2j6zudqssh0lunfnhua7jrczdyjuk97edaswt2fpj",
"foo":"tmltk1e7egscactagl7e3met67658hpl4vf9ux0ralaculjvnzhtc4qmsqv9y857"
},
"eth_flavor_specific_config":{
"":{
"token_config":{
"bar":{
"address":"0x7f6dae09b819f918314d86466a9af4564d3ed805",
"max_amount_per_request":null
},
"foo":{
"address":"0xb87a9b1cafb3b42ea7e2cb3a72b20c5695994a53",
"max_amount_per_request":"1000.5"
}
},
"infura_rpc_url":"https://sepolia.infura.io/v3/1c4fd1ef43ca40deb35e81bc47838b3f",
"bridge_contract_address":"0x0b3c26e254ab5e8c9d84ccdcf1957bed0890322c",
"e2m":null,
"m2e":{
"deposit_tx_required_confirmations":1,
"deposit_tx_destination":"tmt1q94w2g3vwvw74swj3gx4kaf5qelapmdhyyyxe3ef",
"deposit_tx_max_blocks_to_wait":10,
"withdrawal_tx_required_confirmations":1,
"resend_withdrawal_tx_after_block_count":2,
"multisend_contract_address":"0x38869bf66a61cf6bdb996a6ae40d5853fd43b526",
"gnosis_safe_address":"0xb0b61e0aaf88bc40065739112cd2347fcde3f906"
}
},
"xyz":{
"token_config":{
"bar":{
"address":"0xc00f017fbd014a4daa7898b20781508c388253a8",
"max_amount_per_request":null
},
"foo":{
"address":"0x4ef442684ef3d050c6bd54a25d4ea95d688a74e5",
"max_amount_per_request":"1000.5"
}
},
"infura_rpc_url":"https://something-else.infura.io/v3/1c4fd1ef43ca40deb35e81bc47838b3f",
"bridge_contract_address":"0x80285cc9ccb49456709242c18f50e60195b371be",
"e2m":{
"deposit_tx_required_confirmations":1,
"ml_token_owner_address":"tmtc1qnw7qgm87l0a0vhegyrw5szrgqlldkt8rczqzpc2",
"tx_fee_change_address":"tmt1q9pfchtsepyy6n8hx3w74e7tm3pcv5y6ncjtjysg",
"bridge_contract_deposit_log_record_topic":"0x2dc24880b34b2026fb1cd0231e65ef42ca1c78e4efdd9711b7629740206bfa46",
"deposit_tx_max_blocks_to_wait":10,
"withdrawal_tx_required_confirmations":1,
"resend_withdrawal_tx_after_block_count":2
},
"m2e":{
"deposit_tx_required_confirmations":1,
"deposit_tx_destination":"tmt1qxm8pnvpu5886kun0vv9dqzp3nxvhawgqugprcv3",
"deposit_tx_max_blocks_to_wait":10,
"withdrawal_tx_required_confirmations":1,
"resend_withdrawal_tx_after_block_count":2,
"multisend_contract_address":"0x38869bf66a61cf6bdb996a6ae40d5853fd43b526",
"gnosis_safe_address":"0x9f7ed25b653dfedf775b55077f0025722abd7c9f"
}
}
}
}