0xMiden / 0xMiden/wallet-adapter

Sending a note bricks the wallet if NoteMetadata sender is not the wallet account itself

Open
#89 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
2
Forks
9
Avg merge
25m
Merged PRs (30d)
1

Description

### Packages versions

"@miden-sdk/miden-sdk": "0.14.10",
"@miden-sdk/miden-wallet-adapter": "0.14.3",
"@miden-sdk/react": "0.14.10",

### Bug description

Sending a note bricks the wallet if NoteMetadata sender is not the wallet account itself.

For example on p2ide like this:

```tsx
const noteBuilt = createP2IDENote({
from: notWalletAccountId,
to: whomeverAccountId,
assets: { token: fungibleFaucetId, amount: fungibleAmount },
type: NoteVisibility.Public,
reclaimAfter: P2IDE_RECLAIM_AFTER,
timelockUntil: P2IDE_TIMELOCK_UNTIL,
});
```

Closing / restarting browser does not help. Only reinstalling the wallet helps recover the account.

### How can this be reproduced?

Run the below example or run/take the code from here: https://github.com/0x0-mico/miden_consumable_notes/blob/another-sender/src/main.tsx

It will create a P2IDE note and try to send it to the network
Observe that this will brick the wallet:

It will be executing forever:
Image

And wallet will "lose connection" to the node
Image

```tsx
import {
AccountId,
createP2IDENote,
Note,
NoteArray,
NoteVisibility,
TransactionRequestBuilder,
} from '@miden-sdk/miden-sdk';
import {
ConsumeTransaction,
CustomTransaction,
MidenWalletAdapter,
MidenWalletName,
PrivateDataPermission,
Transaction,
TransactionType,
useWallet,
WalletAdapterNetwork,
WalletModalProvider,
WalletMultiButton,
WalletProvider,
} from '@miden-sdk/miden-wallet-adapter';
import '@miden-sdk/miden-wallet-adapter/styles.css';
import { MidenProvider, useMiden } from '@miden-sdk/react';
import { useEffect, useState } from 'react';
import { createRoot } from 'react-dom/client';

const midenWalletAdapters = [new MidenWalletAdapter({ appName: 'position-consume' })];
const poolAccountId = AccountId.fromBech32('mtst1azplz9r5fyw36grz8s92cenuns80075k');

/** Reclaim enabled (non-zero); timelock 0 = unlocked at any block height. */
const P2IDE_RECLAIM_AFTER = 1;
const P2IDE_TIMELOCK_UNTIL = 0;

function App() {
const { isReady } = useMiden();
const { connected, address, select, requestTransaction, requestAssets, requestConsume } = useWallet();
const [p2ideNote, setP2ideNote] = useState(null);
const [message, setMessage] = useState('');

useEffect(() => {
select(MidenWalletName);
}, [select]);

async function p2ideMain(step: 'open' | 'reclaim') {
if (!isReady || !connected || !address || !requestTransaction) {
setMessage('connect wallet first');
return;
}
try {
setMessage('');
if (step === 'open') {
if (!requestAssets) return;
const walletAssets = await requestAssets();
const firstWalletAsset = walletAssets[0];
if (!firstWalletAsset) {
setMessage('wallet has no assets');
return;
}
const fungibleFaucetId = AccountId.fromBech32(firstWalletAsset.faucetId);
const fungibleAmount = BigInt(firstWalletAsset.amount) / BigInt(10);
const noteBuilt = createP2IDENote({
from: poolAccountId,
to: poolAccountId,
assets: { token: fungibleFaucetId, amount: fungibleAmount },
type: NoteVisibility.Public,
reclaimAfter: P2IDE_RECLAIM_AFTER,
timelockUntil: P2IDE_TIMELOCK_UNTIL,
});
console.log("Note created.")
const openRequest = new TransactionRequestBuilder()
.withOwnOutputNotes(new NoteArray([noteBuilt]))
.build();
await requestTransaction(
new Transaction(
TransactionType.Custom,
new CustomTransaction(address, address, openRequest),
),
);
console.log("Note sent.")
setP2ideNote(noteBuilt);
setMessage(`sent P2IDE ${noteBuilt.id()} → pool`);
return;
}
if (!p2ideNote) {
setMessage('send P2IDE note first');
return;
}
const noteAsset = p2ideNote.assets().fungibleAssets()[0];
if (!noteAsset) {
setMessage('note has no fungible asset');
return;
}
await requestConsume?.(
new ConsumeTransaction(
noteAsset.faucetId().toString(),
p2ideNote.id().toString(),
'public',
Number(noteAsset.amount()),
p2ideNote.serialize(),
),
);
setMessage(`reclaimed ${p2ideNote.id()}`);
setP2ideNote(null);
} catch (error) {
setMessage(String(error));
}
}

return (


P2IDE repro — pool target {poolAccountId.toString()}



{connected && address &&

wallet: {address}

}
p2ideMain('open')}>
send P2IDE note

p2ideMain('reclaim')}>
reclaim (ConsumeTransaction)

{p2ideNote &&

note: {p2ideNote.id().toString()}

}
{p2ideNote &&

script root: {p2ideNote.script().root().toHex()}

}
{message &&

{message}

}

);
}

createRoot(document.getElementById('root')!).render(






,
);

```

### Relevant log output

wallet logs out this:

```shell
INDEX.JS: Error in executeTransaction: Error: failed to execute transaction: invalid transaction request: account interface error: invalid sender account: 0x83f11474491d1d20623c0aac667c9c
at __wbg_Error_8c4e43fe74559d73 (Cargo-DKB2aRX-.js:23077:20)
at miden_client_web.wasm.wasm_bindgen[cb32f6f48015412b]::__wbindgen_error_new::__wbg_Error_8c4e43fe74559d73 externref shim (miden_client_web.d-qyt3-n.wasm:0xc1a487)
at miden_client_web.wasm.miden_client_web[8b5bfd558e02b233]::js_error_with_context:: (miden_client_web.d-qyt3-n.wasm:0xa4ee6c)
at miden_client_web.wasm.::execute_transaction::{closure#0} (miden_client_web.d-qyt3-n.wasm:0xaf47df)
at miden_client_web.wasm.wasm_bindgen_futures[203ad115dbfdc77c]::future_to_promise::<::execute_transaction::{closure#0}::_::__wasm_bindgen_generated_WebClient_executeTransaction::{closure#0}>::{closure#0}::{closure#0} (miden_client_web.d-qyt3-n.wasm:0x93423b)
at miden_client_web.wasm.::run (miden_client_web.d-qyt3-n.wasm:0xa8ae5c)
at miden_client_web.wasm.::spawn::::pull::{closure#0}>, ::pull::{closure#1}>>>::{closure#0}::{closure#0}>::{closure#0} (miden_client_web.d-qyt3-n.wasm:0xbb64a8)
at miden_client_web.wasm.wasm_bindgen[cb32f6f48015412b]::convert::closures::_::invoke:: (miden_client_web.d-qyt3-n.wasm:0xc19131)
at miden_client_web.wasm.wasm_bindgen[cb32f6f48015412b]::convert::closures::_::invoke:: externref shim (miden_client_web.d-qyt3-n.wasm:0xc1c4a3)
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.