Skip to content

Commit

Permalink
fixed UI dialogs, ready for reaudit
Browse files Browse the repository at this point in the history
  • Loading branch information
paulfears committed Oct 22, 2024
1 parent a5c2db7 commit db12e02
Show file tree
Hide file tree
Showing 16 changed files with 366 additions and 48 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"lint:fix": "yarn lint:eslint --fix && yarn lint:misc --write",
"lint:misc": "prettier '**/*.json' '**/*.md' '!CHANGELOG.md' --ignore-path .gitignore",
"serve": "mm-snap serve",
"test": "mm-snap build && concurrently \"(mm-snap serve)\" \"http-server ./test\"",
"test": "mm-snap build && concurrently \"(mm-snap serve)\" \"http-server -p 3000 ./test\"",
"start": "npx mm-snap build && concurrently \"(npx mm-snap serve)\" \"npm install --prefix ./site/ && npm run --prefix ./site/ dev\""
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion site/src/routes/docs/QuickStart.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ async function callMetaStellar(method, params){
<TypescriptContainer code={MetaStellar_String} desc={callMetastellarDesc}/>
<br/>
<br/>
<div class="uk-container justify-center" shadow>
<div class="uk-container justify-center" >
<div>
The callMetaStellar Function is a one stop soultion to accessing a users stellar-metamask wallet.
Simply run <b>callMetaStellar('connect')</b> to connect and install stellar onto a users Metamask!
Expand Down
25 changes: 25 additions & 0 deletions site/src/routes/docs/methods.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,31 @@ let openSendXLM = `callMetaStellar('openSendXLM');`;


<Heading>getDataPacket</Heading>
<!--
<div>
<P>Grabs Useful infomation About the users Stellar Wallet</P>
<P>Returns:</P>
<div id="datapacketType">
<p>this is the type returned from the getDataPacket method</p>
<code>
<pre>
{`
interface DataPacket{
name:string,
currentAddress:string,
mainnetAssets?:`} <a>walletAsset[],</a>
{`testnetAssets?: `} <a>walletAsset[],</a>
{`accounts: Array< {name:string, address:string} >
mainnetXLMBalance: string,
testnetXLMBalance: string,
fedName: string | null
}`}
</pre>
</code>
</div>
</div>
-->
<h2>callMetaStellar('getDataPacket')</h2>
<Editor code={getDataPacket}/>

Expand Down
132 changes: 132 additions & 0 deletions site/src/routes/docs/types.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<script lang='ts'>
import Editor from "$lib/components/Editor/Editor.svelte";
let dataPacketString = `
export interface DataPacket{
name:string,
currentAddress:string,
mainnetAssets?: walletAsset[],
testnetAssets?: walletAsset[],
accounts: Array<{name:String, address:String}>
mainnetXLMBalance: string,
testnetXLMBalance: string,
fedName: string | null
}
`
</script>

<div id="datapacketType">
<h2>DataPacket</h2>
<p>this is the type returned from the getDataPacket method</p>
<code>
<pre>
{`
interface DataPacket{
name:string,
currentAddress:string,
mainnetAssets?:`} <a>walletAsset[],</a>
{`testnetAssets?: `} <a>walletAsset[],</a>
{`accounts: Array< {name:string, address:string} >
mainnetXLMBalance: string,
testnetXLMBalance: string,
fedName: string | null
}`}
</pre>
</code>
</div>


<div id="walletAssetType">
<h2>WalletAsset</h2>
<p>the type of the assets in the mainnetAssets and testnetAssets arrays</p>
<code>
<pre>
{`
type walletAsset = AssetBalance | NativeBalance
`}
</pre>
</code>
</div>


<div id="NativeBalanceType">
<h2>NativeBalance Type</h2>
<p>Infomation about a given wallets XLM Balance</p>
<code>
<pre>
{`
interface NativeBalance{
balance:string, // number or decimal number in string format (max 7 decimal places) may be big number
liquidity_pool_id?:string,
limit: string,
buying_liabilites: string,
selling_liabilites: string,
sponser?: string,
last_modified_ledger: number,
is_authorized: boolean,
is_authorized_to_maintain_liabilites: boolean,
is_clawback_enabled: boolean,
asset_type: "native",
asset_issuer: "native"
asset_code: "XLM"
}
`}
</pre>
</code>
</div>
<div id="AssetBalanceType">
<h2>AssetBalance Type</h2>
<p>Infomation about a given wallets balance of a specific asset</p>
<code>
<pre>
{`
interface AssetBalance{
balance:string, // number or decimal number in string format (max 7 decimal places) may be big number
liquidity_pool_id?:string, //number
limit: string, //number
buying_liabilites: string, //number
selling_liabilites: string, //number
sponser?: string, //address
last_modified_ledger: number,
is_authorized: boolean,
is_authorized_to_maintain_liabilites: boolean,
is_clawback_enabled: boolean,
asset_type: "credit_alphanum4"|"credit_alphanum12"
asset_code: string, // example: USDC, wBTC, wEth
asset_issuer: string, //address
}
`}
</pre>
</code>
</div>

<div id='SimpleAccountType'>
<h2>SimpleAccount Type</h2>
<p>Infomation about a given wallets balance of a specific asset</p>
<code>
<pre>
{`
interface SimpleAccount{
name:string,
address:string
}
type AccountList = SimpleAccount[]
`}
</pre>
</code>
</div>
<style>
a{
color: #aaa;
text-decoration: underline;
}
pre{
background-color: #333;
color: white;
padding: 10px;
border-radius: 5px;
}
</style>
2 changes: 1 addition & 1 deletion snap.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://github.com/paulfears/StellarSnap.git"
},
"source": {
"shasum": "WCKcDYLPysLb4iYtokYDgCj3XxYfGbYLKJHDKLy+XWQ=",
"shasum": "T5VbYPw/j/r1shsNJhw2LOv1mDCwHBDOzqkfWX9nA9A=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
5 changes: 4 additions & 1 deletion snap/Auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Keypair } from "stellar-base";
import { Wallet } from "./Wallet";
import {panel, text, heading, divider, copyable} from '@metamask/snaps-ui';
import Utils from "./Utils";
import { InteractionHandler } from "./InteractionHandler";
const proof = {};
interface AuthRequest{
[key: number]:any,
Expand Down Expand Up @@ -37,7 +38,9 @@ export class Auth{
let displayPanel = panel([
heading('Sign Text?'),
divider(),
copyable(data)
copyable(data),
divider(),
text('request from: '+InteractionHandler.requestOrigin)
])
const confirmation = await Utils.displayPanel(displayPanel);
if(!confirmation){
Expand Down
16 changes: 15 additions & 1 deletion snap/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ Class for utility functions
wallet is a global in the metamask context
*/
import { DialogResult } from '@metamask/snaps-sdk';
import { ComponentOrElement, DialogResult } from '@metamask/snaps-sdk';
import { panel, text, heading, divider, copyable, Panel } from '@metamask/snaps-ui';
type interfaceId = string;
import { InteractionHandler } from './InteractionHandler';
import { SnapComponent } from '@metamask/snaps-sdk/jsx';
import type { SnapElement } from '@metamask/snaps-sdk/jsx';
export default class Utils {

static throwError(code, msg){
Expand Down Expand Up @@ -104,6 +106,18 @@ export default class Utils {
return alert;
}

static async openDialogWithContent(content:ComponentOrElement, type:'confirmation' | "alert" | 'prompt'): Promise<DialogResult>{
const disp = await snap.request({
method: 'snap_dialog',
params:{
type: type,
content:content
}
})
return disp
}


static async displayPanel(disppanel: Panel, type:"confirmation" | "alert" | "prompt" = "confirmation"): Promise<DialogResult>{
const disp = await snap.request({
method: 'snap_dialog',
Expand Down
82 changes: 70 additions & 12 deletions snap/Wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import Utils from './Utils';
import { panel, text, heading, image, copyable, divider} from '@metamask/snaps-ui';
import QRcode from "qrcode-svg";
import { lookupAddress } from './federation';
import {CreateNewAccountConfimation} from './screens/newAccount';
import { switchAccountDialog } from './screens/switchAccount';

import type { SimpleAccount } from 'types';

export class Wallet{
keyPair: Keypair;
Expand Down Expand Up @@ -59,7 +62,29 @@ export class Wallet{
return Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)))
}

static async createNewAccount(name:string, currentState?:State, setState?:boolean):Promise<Wallet>{
static async CreateNewAccountDialog(name:string, switchAccount?:boolean):Promise<SimpleAccount|void>{

if(switchAccount === undefined){
switchAccount = true;
}
const confirm = await CreateNewAccountConfimation(name);
let output = null;

if(confirm){

const createdWallet = await Wallet.createNewAccount(name, undefined, true);
if(switchAccount){
await Wallet.setCurrentWallet((createdWallet as SimpleAccount).address);
}
return createdWallet;
}
else{
return Utils.throwError(400, "user rejected request");
}

}

static async createNewAccount(name:string, currentState?:State, setState?:boolean):Promise<SimpleAccount|void>{
if(currentState === undefined){
currentState = await StateManager.getState();
}
Expand All @@ -77,15 +102,23 @@ export class Wallet{
console.log("salt is: "+salt);
let tempAccount = await Wallet.getTempAccountFromSalt(salt);
tempAccount.name = name;

//make sure name dosn't already exist
for(let account of Object.values(currentState.accounts)){
if(account.name === name){
return Utils.throwError(400, "account name already exists");
}
}

currentState.accounts[tempAccount.address] = tempAccount;
if(currentState.currentAccount === null || numAccounts === 0){

if(currentState.currentAccount === null){
currentState.currentAccount = tempAccount.address;
}
if(setState){
await StateManager.setState(currentState);
}

return new Wallet(tempAccount, currentState);
return {address:tempAccount.address, name:tempAccount.name};
}

static async renameWallet(address:string, name:string, currentState?:State):Promise<boolean>{
Expand Down Expand Up @@ -113,27 +146,35 @@ export class Wallet{
let walletAccount:walletAccount;
if(currentState.currentAccount === null){
console.log("current State is null");
return await Wallet.createNewAccount('Account 1', currentState, setState);

let success = await Wallet.createNewAccount('Account 1', currentState, setState);
if(!success){
Utils.throwError(400, "account failed to create");
}
}
else{
console.log("wallet Account found")
walletAccount = currentState.accounts[currentState.currentAccount]
}
walletAccount = currentState.accounts[currentState.currentAccount as string] as walletAccount;

return new Wallet(walletAccount, currentState);

}

static async setCurrentWallet(address:string, origin:string, currentState?:State){
static async setCurrentWallet(address:string, currentState?:State):Promise<SimpleAccount>{
let valid = StrKey.isValidEd25519PublicKey(address);
if(!valid){
Utils.throwError("404", "invalid address");
}
if(currentState === undefined){
currentState = await StateManager.getState();
}
const name = currentState.accounts[address].name

let name;
if(currentState.accounts[address]){
const confirm = await Screens.confirmAccountChange(origin, name, address);
name = (currentState.accounts[address] as walletAccount).name;
address = address;
const confirm = await switchAccountDialog(address);
if(confirm){
currentState.currentAccount = address;
await StateManager.setState(currentState);
Expand All @@ -146,7 +187,7 @@ export class Wallet{
else{
Utils.throwError("404", "account not found");
}
return {address, name};
return {name:name as string, address: address};
}

static async getSeedFromSalt(salt){
Expand Down Expand Up @@ -208,15 +249,32 @@ export class Wallet{
return currentState;
}

static async listAccounts(currentState?:State){
static async getAccount(address:string, currentState?:State):Promise<SimpleAccount | void>{
if(currentState === undefined){
currentState = await StateManager.getState();
}
let account = currentState.accounts[address];
if(!account){
return Utils.throwError(404, "account not found");
}
else{
return {
name: account.name,
address: account.address
}
}

}

static async listAccounts(currentState?:State):Promise<SimpleAccount[]>{
console.log("list accounts");
if(currentState === undefined){
console.log("currentState is undefined")
currentState = await StateManager.getState();
console.log(currentState);
}
console.log(currentState.accounts);
let output:Array<{"name":String, "address":String}> = []
let output:Array<{"name":string, "address":string}> = []
console.log(currentState.accounts);
for(let account of Object.values(currentState.accounts)){
console.log(account);
Expand Down
Loading

0 comments on commit db12e02

Please sign in to comment.