-
Notifications
You must be signed in to change notification settings - Fork 208
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(wallet-connection): Connect dapp directly to wallet UI #5750
Conversation
0580cac
to
16d853c
Compare
window.parent.postMessage({ type: 'walletBridgeLoaded' }, '*'); | ||
} | ||
retryWebSocket(); | ||
window.addEventListener('load', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This ensures the message wont be posted until after the iframe's "onLoad" event fires. This is the way it works with the react bridge.jsx, so we can rely on the consistent ordering of events in the WalletConnection component.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems pretty good, but given the low test coverage for this stuff, I'd like to give @turadg a chance to look it over
docs/env.md
Outdated
Until dApps are converted to connect to the smart-wallet UI directly, | ||
this allows them to continue to connect to `/wallet-bridge.html` and such | ||
on the solo and have these endpoints serviced by `/wallet/bridge.html` | ||
and such in a wallet UI. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wasn't clear to me from reading this what the purpose was (the difference between the two paths or how it worked.)
Consider:
This enables a proxy so that the solo bridge interface (
/wallet-bridge.html
) is backed by the smart wallet(/wallet/bridge.html)
. Dapps designed for the solo bridge can enable this until they connect to the smart wallet directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
window.parent.postMessage({ type: 'walletBridgeLoaded' }, '*'); | ||
} | ||
retryWebSocket(); | ||
window.addEventListener('load', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
your PR comment would make a good code comment.
window.addEventListener('load', () => { | |
// This ensures the message wont be posted until after the iframe's "onLoad" event fires | |
// so we can rely on the consistent ordering of events in the WalletConnection component. | |
window.addEventListener('load', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, please!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
</head> | ||
|
||
<body style="overflow-x: hidden; overflow-y: scroll"> | ||
<noscript>Without JavaScript enabled, this page cannot function.</noscript> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that statement is true invariantly. minor but let's tell the user something about the state.
<noscript>Without JavaScript enabled, this page cannot function.</noscript> | |
<noscript>ERROR: JavaScript not available.</noscript> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough. Better to be explicit and tell them how to fix it?
I have a hard time blaming the user when the page requires JavaScript. I was trying to concisely say something like "Please excuse the requirement for you to put yourself at risk by enabling JavaScript in your browser. This page uses JavaScript for more than progressive enhancement. Providing similar functionality without JavaScript is not practical."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just used the same message as index.html. Do people still use the web without javascript? At the very least they're trying to use a dapp so I don't think we need to be apologetic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... so I don't think we need to be apologetic.
No, we don't need to, but...
Do people still use the web without javascript?
Yes. In fact, I bet you do it regularly, with curl
and the like.
); | ||
} else { | ||
console.debug('bridge: SKIP document.requestStorageAccess'); | ||
conn.connectStorage(window.localStorage); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could this fail?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I don't think so. It only calls addEventListener
; I don't see how that could fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've been bitten by localStorage
permission problems, but I suppose if you've got the object you won't find out about any errors until mutating. And even then you could have failures later with hitting quotas, the permission being revoked, etc. So fine to handle those cases later.
@@ -28,7 +30,17 @@ const WalletConnection = ({ | |||
connectionConfig, | |||
}) => { | |||
const classes = useStyles(); | |||
const [wc, setWC] = useState(null); | |||
/** | |||
* ISSUE: where to get the full types for these? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
e.g. for WalletConnection at this line to the bottom of AgoricWalletConnection.js
,
/** @typedef {InstanceType<AgoricWalletConnection>['walletConnection']} FarWalletConnection */
I suggest "Far" to distinguish from the other "WalletConnection" strings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't get this working
localStorage: storage, | ||
addEventListener, | ||
removeEventListener, | ||
} = window; // WARNING: ambient |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider using window.
at each access so the ambience is apparent at the callsite
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather go the other direction: pass in these parts of window
explicitly rather than using window
ambiently.
OTOH, window.addEventListener
is quite likely more conventional and easier to read, and since the current code doesn't follow ocap discipline, maybe making it easier to read is better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Switched to window.
removeEventListener, | ||
} = window; // WARNING: ambient | ||
|
||
function handleStorageMessage(key, newValue) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a lot of logic in here that's not UI concern. consider extracting some to a utility function. that could be unit tested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
concur
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pulled this into a separate function. I don't know how much of this code is just placeholder/PoC until after we have the smart wallet bridge fully working, so I won't bother writing tests yet.
// eslint-disable-next-line no-restricted-properties | ||
const { pow: mathPow } = Math; | ||
// eslint-disable-next-line no-restricted-properties | ||
Math.pow = (base, exp) => | ||
typeof base === 'bigint' && typeof exp === 'bigint' | ||
? base ** exp | ||
: mathPow(base, exp); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we not have a shim that can be called to do this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Umm... This is such a shim, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean one that can be imported here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty sure this is a one-off. It's kind of a kludge, really.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not a new kludge, btw. It comes from...
agoric-sdk/packages/wallet/ui/public/index.html
Lines 12 to 15 in 39fe092
Math.pow = (base, exp) => | |
typeof base === 'bigint' && typeof exp === 'bigint' | |
? base ** exp | |
: mathPow(base, exp); |
Git says that's from @samsiegart Oct 2021 01a9118 but I suspect it predates that too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah. Where is it used? I can't find any instances. If there are any consider making them bigint-safe there instead of modifying Math
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know where it's used. Maybe some 3rd party library?
I sure wish we had made a test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes this code has been here longer than I have, will leave this convo open but won't block this PR on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's at least a step in the right direction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- document SOLO_BRIDGE_TARGET
it worked up to making an offer; the trade didn't complete... not sure why - much wrestling with webpack magic in config-overrides to add wallet/bridge.html entry point - move lockdown() call from .html to .jsx - HandledPromise identity discontinuity musings
- JSON.stringify is more familiar
fff0237
to
688cc2b
Compare
* chore(web-components): revert casting experiment * feat(solo): transitional reverse-proxy wallet-bridge - document SOLO_BRIDGE_TARGET * feat(wallet/api): E(walletAdmin).getScopedBridge() * build(wallet/ui): deps += react-app-rewire-multiple-entry * feat(wallet/ui): localStorage bridge functional in AMM (WIP) it worked up to making an offer; the trade didn't complete... not sure why - much wrestling with webpack magic in config-overrides to add wallet/bridge.html entry point - move lockdown() call from .html to .jsx - HandledPromise identity discontinuity musings * chore(wallet/ui): prune bridge.html to essentials * doc(casting): package name typo in README * refactor(wallet/ui): take advantage of ev type - JSON.stringify is more familiar * chore: sameParent is evidently superfluous * chore: delay storage listener until user requests * chore: gate storage connection on requestStorageAccess * chore: sameParent check before postMessage. noop??? * feat: use correct bridge url * feat: amm swap working * chore: prettier * fix: address feedback * chore: rebase Co-authored-by: Dan Connolly <connolly@agoric.com>
refs: #3995
We can now add the
useLocalStorage={true}
property to the wallet connection component to get the dapp to talk directly to the wallet UI in local storage, that way the dapp doesn't directly depend on an ag-solo connection.