The MoneriumPack
enables Safe users to make direct transfers of e-money tokens from their Safe accounts to an IBAN via the SEPA network. This allows them to use Monerium and Safe services together.
More info about Monerium:
This guide demonstrates how to use the MoneriumPack
as part of the OnRampKit
and incorporate it into your web application.
- Node.js and npm
- Monerium account and application
- A web application using your favorite CLI and language. For example:
Monerium offers several authentication methods for web apps. The MoneriumPack
implements the Authorization code flow with proof key for code exchange (PKCE).
yarn add @safe-global/onramp-kit @safe-global/protocol-kit @monerium/sdk
Creating a Login with Monerium integration for the Safe requires a multi-step process that should be implemented in your web app. The following steps are required.
- Load the application and initialize the
MoneriumPack
using the following snippet:
import { MoneriumPack } from '@safe-global/onramp-kit'
const moneriumPack = new MoneriumPack({
clientId: { YOUR_CLIENT_ID }, // Get your client id from Monerium
environment: 'sandbox' // Use the proper Monerium environment ('sandbox' | 'production')})
})
await moneriumPack.init({ safeSdk })
The safeSdk
is an instance of the Safe
class. For more information on how to instantiate the protocol-kit
refer to the Protocol Kit Quickstart section.
The MoneriumPack
will use the Safe account address configured in the safeSdk
to link to your Monerium account.
- Start the Login with Monerium flow by creating a button or link in your application. Use your favorite UI library to add a handler and start the login flow. In the button handler you should start the flow by calling the
open
method:
await moneriumPack.open({ redirectUrl: 'https://your-site-redirect-url' })
This action will open the Monerium web page to begin the authentication process and get the permissions to gain access to your information.
Take a look to the Monerium web page URL. You will see that the query string includes parameters such as these, among others:
address
: The Safe address you want to bind to your Monerium account.signature
: Always "0x". It means the origin wallet is a multisig, just like the Safe. Monerium will then verify for onchain signatures in your Safe contractchain
: The Monerium selected chain. The value is automatically calculated using thesafeSdk
instance.network
: The Monerium selected network. The value is automatically calculated using thesafeSdk
instance.redirect_uri
: TheredirectUrl
you sent in theopen
method. Once authenticated Monerium dashboard will redirect to that url.
signMessage
transaction accepting the required Monerium message will be proposed to your Safe the first time you try to link your Safe address. To confirm and execute it, you must also add the remaining signatures in the Safe UI and execute the transaction.
Once you are in the Monerium web page, you should login or create a new account if you don't have one already.
After that, the Monerium UI, will wait until it detects the Safe address has signed the message as explained above and the transaction is executed. You may need to reload the Monerium UI page once you know the transaction was executed in order to continue with the flow. Alternatively, you can start the process again and Monerium will detect the transaction confirmation immediately.
Note. If you use the sandbox
environment, you can test this flow without KYC in Goerli
. To use the mainnets for ethereum
, gnosis
or polygon
in production, you need to create an account in the Monerium dashboard and complete KYC. The production
environment involves real money, whereas the sandbox
environment uses fake money and test tokens.
-
Once you authenticate through the Monerium UI, a window will appear asking for permission to access your information. If you accept, control will be returned to the
redirectUrl
you specified in theopen
method. -
The
redirectUrl
used in theopen
will be reached again with an extra query string parametercode
. This is the authorization code you need to exchange in order to gain access to your Monerium account.
Re-initialize the MoneriumPack
using the init
method and exchange the code, as per Step 1.
const safeMoneriumClient = await moneriumPack.open({ authCode: '<The querystring code parameter>' })
If the code is exchanged successfully, you will be now authenticated with Monerium and your Safe will be linked!. You can start using the safeMoneriumClient
instance to interact with your Monerium account. This instance is an enhanced version of the Monerium SDK, with some additional Safe features.
To learn more about the methods you can use with the safeMoneriumClient
instance, check the Monerium SDK documentation.
Here are some examples:
const authContext = await moneriumClient.getAuthContext()
const profile = await moneriumClient.getProfile(authContext.defaultProfile)
const balances = await moneriumClient.getBalances()
const orders = await moneriumClient.getOrders()
- When you reload a page, you usually want to stay authenticated as long as the tokens are valid. To do this, we have another way to
open()
theMoneriumPack
.
Once authenticated in step 4, you can store the refresh_token
found in the bearerProfile
property of the safeMoneriumClient
using browser storage methods.
localStorage.setItem(
'MONERIUM_TOKEN',
safeMoneriumClient.bearerProfile.refresh_token
)
If the user leaves the session or reloads the browser, detect and retrieve the stored token on the next session or page load. Always init
the MoneriumPack
instance when the page loads as showed in the step 1.
const safeMoneriumClient = await moneriumPack.open({
refreshToken: localStorage.getItem('MONERIUM_TOKEN')
})
- You're now ready to place orders. In the
production
environment, real funds will be transferred. In thesandbox
environment, fake money will be used. If you add funds using thesandbox
or create a transfer from your bank account to your Monerium IBAN in theproduction
environment, you'll receive the corresponding tokens in your Safe. For example, if your Monerium IBAN is associated with the EURe token of your Safe, and you transfer 10 euros, the EURe balance of your Safe will be 10 after the SEPA system completes the transfer.
Add tokens to your Safe using the sandbox
. They should be available almost instantly. You can check the balance of your assets here afterwards.
Once you have tokens, you can create a redeem
order to burn them and convert them to fiat. Include a text box for an IBAN and a button to place the order. Add a handler for the button and do the following:
safeMoneriumClient.send({
amount: '10',
currency: Currency.eur, // You can redeem the currency of your choice. Your Monerium IBAN will be linked to a single token.
counterpart: {
identifier: {
standard: 'iban',
iban: 'The IBAN to send the money to',
},
details: {
firstName: 'John',
lastName: 'Doe',
country: 'You ISO country code',
},
},
memo: 'Testing Safe-Monerium integration'
})
Once you place your order, it will be sent to the destination account. Two things will occur:
- A
signMessage
transaction will be proposed to the Safe services indicating in the message the amount of tokens to burn and the destination IBAN. To verify the message to be signed, refer to the API docs. You should confirm and execute it using the Safe UI or an alternative method as the transaction data is returned in thesend()
call. - An order is placed in the Monerium system, it listens for the
signMessage
transaction above to be confirmed and executed.
Once the transaction is recorded on the blockchain, the token is burned and the transfer of real money begins, completing the order 🚀.
- Listening to events is important for understanding what is happening around. It helps us to create a proper UI in our web page.
You probably want to know when the order is completed. For this you can listen to events using the Monerium API websockets
Connecting to the socket is easy, just use the moneriumPack
instance along with the subscribe()
and unsubscribe()
methods.
To subscribe, do this:
const handler = (notification) => {
console.log(notification)
}
moneriumPack.subscribe(OrderState.processed, handler)
The potential states are this ones:
OrderState {
placed = 'placed',
pending = 'pending',
processed = 'processed',
rejected = 'rejected'
}
If you wish to unsubscribe, you can do:
moneriumPack.unsubscribe(OrderState.processed, handler)
Check a complete example in the safe-core-sdk
repo. Follow the steps in the README.md
to run the example and configure the environment variables for the pack following the .env.sample
.