<<<<<<< HEAD
adds stellar to metamask, by creating a non-custodial wallet built directly into metamask
calling this method will connect to metamask and automatically install the snap if it isn't already installed. As well as generate the users wallet. Calling this method or any subsequent methods does not requiring installing anything to a webpage, provided the the user has metamask (flask) installed.
const result = await ethereum.request({
method: 'wallet_requestSnaps',
params: {
[`npm:stellar-snap`]: {}
},
});
example method call
const result = await ethereum.request({
method: 'wallet_invokeSnap',
params: {`npm:stellar-snap`, request:{
method: `${methodName}`,
params:{
paramName: `${paramValue}`
}
}}
})
by default all methods are treated as mainnet, but any method can be issued to the testnet by using the testnet param.
example:
const result = await ethereum.request({
method: 'wallet_invokeSnap',
params: {snapId:`npm:stellar-snap`, request:{
method: `getBalance`,
params:{
testnet: true
}
}}
})
returns the accounts address as a string
const address = await ethereum.request({
method: 'wallet_invokeSnap',
params: {snapId:`npm:stellar-snap`, request:{
method: `getAddress`,
}}
})
grabs infomation related to the account requires account to be funded
const info = await ethereum.request({
method: 'wallet_invokeSnap',
params: {snapId:`npm:stellar-snap`, request:{
method: `getAccountInfo`,
params:{
testnet?: true | false
}
}}
})
gets the XLM balance of a wallet, returns 0 in unfunded wallets
const balance = await ethereum.request({
method: 'wallet_invokeSnap',
params: {snapId:`npm:stellar-snap`, request:{
method: `getBalance`,
params:{
testnet?: true | false
}
}}
})
this method is used to transfer xlm and requires a funded account. after being called the wallet will generate a transaction, then prompt a user to accept if the user accepts the transaction it will be signed and broadcast to the network. will return transaction infomation. And send a notification stating whether the transaction was successful.
const transactionInfomation = await ethereum.request({
method: 'wallet_invokeSnap',
params: {snapId:`npm:stellar-snap`, request:{
method: `getBalance`,
params:{
to: 'stellarAddress' //string
amount: '1000.45' //string represention of amount xlm to send
testnet?: true | false
}
}}
})
this method funds the users wallet on the testnet
const success = await ethereum.request({
method: 'wallet_invokeSnap',
params: {snapId:`npm:stellar-snap`,
request:{
method: 'fund'
}
}
})
This method signs an Arbitary Transaction
async function signTransaction(){
const transaction = new StellarSdk.TransactionBuilder(account, { fee, networkPassphrase: "Test SDF Network ; September 2015" });
// Add a payment operation to the transaction
console.log("transaction builder initilazed");
await transaction.addOperation(StellarSdk.Operation.payment({
destination: receiverPublicKey,
// The term native asset refers to lumens
asset: StellarSdk.Asset.native(),
// Specify 350.1234567 lumens. Lumens are divisible to seven digits past
// the decimal. They are represented in JS Stellar SDK in string format
// to avoid errors from the use of the JavaScript Number data structure.
amount: '350.1234567',
}));
console.log("operations added")
// Make this transaction valid for the next 30 seconds only
await transaction.setTimeout(30);
console.log("timeout set");
// Uncomment to add a memo (https://www.stellar.org/developers/learn/concepts/transactions.html)
// .addMemo(StellarSdk.Memo.text('Hello world!'))
const endTransaction = await transaction.build();
const xdrTransaction = endTransaction.toXDR();
console.log(xdrTransaction);
const response = await ethereum.request({
method: 'wallet_invokeSnap',
params:{snapId:snapId, request:{
method: 'signTransaction',
params:{
transaction: xdrTransaction,
testnet: testnet
}
}}
})
console.log(response);
}
The Wallet also supports sorroban, To sign a SorobanCall futurenet must be set to true on the params object.
async function callContract() {
console.log("here in callContract");
const sourcePublicKey = await ethereum.request({
method: 'wallet_invokeSnap',
params: {snapId:snapId, request:{
method: 'getAddress',
}}
})
const server = new SorobanClient.Server('https://rpc-futurenet.stellar.org');
console.log("getting account")
const account = await server.getAccount(sourcePublicKey);
console.log("account is: ")
console.log(account);
console.log(SorobanClient);
const contract = new SorobanClient.Contract("CCNLUNUY66TU4MB6JK4Y4EHVQTAO6KDWXDUSASQD2BBURMQT22H2CQU7")
console.log(contract)
const arg = SorobanClient.nativeToScVal("world")
console.log("arg is: ")
console.log(arg)
let call_operation = contract.call('hello', arg);
console.log(call_operation)
let transaction = new SorobanClient.TransactionBuilder(account, { fee: "150", networkPassphrase: SorobanClient.Networks.FUTURENET })
.addOperation(call_operation) // <- funds and creates destinationA
.setTimeout(30)
.build();
console.log(transaction)
const preparedTransaction = await server.prepareTransaction(transaction, SorobanClient.Networks.FUTURENET);
console.log("prepairedTxn: ");
console.log(preparedTransaction);
const tx_XDR = preparedTransaction.toXDR();
const signedXDR = await ethereum.request(
{method: 'wallet_invokeSnap',
params: {
snapId:snapId,
request:{
method: 'signTransaction',
params:{
transaction: tx_XDR,
futurenet: true
}
}
}
}
)
console.log(signedXDR)
try{
const transactionResult = await server.sendTransaction(signedXDR);
console.log(JSON.stringify(transactionResult, null, 2));
console.log('\nSuccess! View the transaction at: ');
console.log(transactionResult)
} catch (e) {
console.log('An error has occured:');
console.log(e);
}
}
foo@bar:~$ yarn
...
foo@bar:~$ npx mm-snap build
...
Build success: 'src\index.ts' bundled as 'dist\bundle.js'!
Eval Success: evaluated 'dist\bundle.js' in SES!
foo@bar:npx mm-snap serve
Starting server...
Server listening on: http://localhost:8080
and just like that you should be good to go.
keys are generated on the fly, anytime a method is invoked. This works by requesting private entropy from the metamask wallet inside of the snaps secure execution enviroment, and using that entropy to generate a users keys. This entropy is static, and based on the users ethereum account. This means that we at no point store keys, and the fissile material is handled by metamask.
Because keys are handled in this way, when a user recovers their metamask account, they will also recover their stellar account, which means that there isn't another mnemonic to save.
This repository demonstrates how to develop a snap with TypeScript. For detailed instructions, see the MetaMask documentation.
MetaMask Snaps is a system that allows anyone to safely expand the capabilities of MetaMask. A snap is a program that we run in an isolated environment that can customize the wallet experience.
To interact with (your) Snaps, you will need to install MetaMask Flask, a canary distribution for developers that provides access to upcoming features.
Clone the template-snap repository using this template and set up the development environment:
yarn install && yarn start
This repository contains GitHub Actions that you may find useful, see
.github/workflows
and Releasing & Publishing
below for more information.
If you clone or create this repository outside the MetaMask GitHub organization,
you probably want to run ./scripts/cleanup.sh
to remove some files that will
not work properly outside the MetaMask GitHub organization.
If you don't wish to use any of the existing GitHub actions in this repository,
simply delete the .github/workflows
directory.
Run yarn test
to run the tests once.
Run yarn lint
to run the linter, or run yarn lint:fix
to run the linter and
fix any automatically fixable issues.
Scripts are disabled by default for security reasons. If you need to use NPM
packages with scripts, you can run yarn allow-scripts auto
, and enable the
script in the lavamoat.allowScripts
section of package.json
.
See the documentation for @lavamoat/allow-scripts for more information.
2467c38 (newSnap Build)