Is IOTA Wallet safe?
IOTA Wallet sends detailed financial activity events — transactions, DApp connections, and key exports — to Amplitude's analytics servers.
When users perform wallet actions such as sending coins, approving transactions, connecting to DApps, or exporting account keys, the extension captures those events along with associated metadata and transmits them via HTTPS to Amplitude's EU-region endpoint. The Amplitude SDK is initialized with a hardcoded API key and also uses navigator.sendBeacon to flush data on page hide and visibility-change events. No confirmed claims establish data collection beyond what the Amplitude integration describes.
Who publishes itIOTA Ecosystem DLT Foundation - no other listings under this identity
IOTA Ecosystem DLT Foundation - no other listings under this identity
What this publisher told the store about itself, and the other listings that told it the same thing.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
IOTA Wallet sends wallet-action analytics to Amplitude
Using select IOTA Wallet features records analytics for sending coins, connecting a DApp, or opening export-keys.
Events POST via HTTPS to Amplitude's EU host with the API key, device ID, and metadata like coin type.
What actually happens
You perform a tracked wallet action inside IOTA Wallet.
Examples in the shipped code include sending coins, connecting a DApp, responding to a transaction request, and choosing Export Account Keys.
The extension creates an analytics event for that action and sends it to Amplitude.
Dynamic analysis observed a POST to Amplitude after wallet activity, and the source contains the matching event names and properties.
Captured request
Dynamic analysis observed the request after wallet activity; the evidence notes a body containing the hardcoded API key, a device ID, and an Amplitude page-location field.
Concrete fields shown by the code and observed traffic
- Analytics project key2a5d35822a1bab41835813f0223f319e
Tells Amplitude which analytics project receives the event from your extension.
- Your analytics device IDd4f2c6b8-9a01-4f32-9d7c-0d1e2f3a4b5c (illustrative)
Lets the analytics service group multiple wallet events from the same browser profile.
- Your page locationchrome-extension://iidjkmdceolghepehaaddojmnjnkkija/ui.html (illustrative)
Shows the extension page context associated with the wallet event.
- Your wallet actionsent coins
Records which wallet feature you used, such as sending coins or starting a DApp connection.
- Your action detailscoinType: IOTA; amount: 1.25; applicationUrl: https://app.example.iota.org (illustrative)
Adds action-specific details, such as the coin type and amount for a send or the application URL for a DApp request.
- Your approval resultapprovedTransaction: true; receivedFailureWarning: false
Shows whether you approved a transaction request and whether the approval followed a warning prompt.
- Your account typePrivate Key
When you open the export-account-keys flow, the analytics event records the account type selected in the wallet.
The code that does this
The shipped extension initializes Amplitude and maps wallet actions to analytics events
Amplitude API key and EU server-zone configuration
background.jslet sa = { iotawallet: "2a5d35822a1bab41835813f0223f319e" }, su = { plan: { version: "3", branch: "main", source: "web", versionId: "41c28342-e260-4c3e-8465-6618203f115a" }, ...{ ingestionMetadata: { sourceName: "browser-typescript-ampli", sourceVersion: "2.0.0" } }, serverZone: tu.EU };EU endpoint selector used by the bundled Amplitude SDK
ui.jsnQ=function(t,n,i){if(void 0===t&&(t=""),void 0===n&&(n=nX().serverZone),void 0===i&&(i=nX().useBatch),t)return{serverUrl:t,serverZone:void 0};var a,o=["US","EU"].includes(n)?n:nX().serverZone;return{serverZone:o,serverUrl:(a=i,"EU"===o?a?"https://api.eu.amplitude.com/batch":"https://api.eu.amplitude.com/2/httpapi":a?"https://api2.amplitude.com/batch":nj)}}Amplitude load function and beacon flush handlers
ui.jsasync function le(){var t;let n,i,a;s8.load({environment:"iotawallet",disabled:!1,client:{configuration:{optOut:!1,identityStorage:"cookie",autocapture:{attribution:!1,fileDownloads:!1,formInteractions:!1,pageViews:!0,sessions:!0,elementInteractions:!1,frustrationInteractions:!1,networkTracking:!1,webVitals:!1,pageUrlEnrichment:!0},logLevel:mB.None,flushIntervalMillis:1e3,flushQueueSize:5}}}),s8.client.add((t=s8.client,n=null,i=null,{name:"dialog-context",type:"enrichment",setup:async()=>(n="u"<typeof window||"u"<typeof document?()=>{}:(document.addEventListener("click",rK,!0),()=>{document.removeEventListener("click",rK,!0)}),i=function(t){if("u"<typeof window||"u"<typeof document)return()=>{};let n=new MutationObserver(n=>{for(let i of n)i.addedNodes.forEach(n=>{if(n instanceof HTMLElement){var i,a;((null==(i=n.matches)?void 0:i.call(n,rH))?n:null==(a=n.querySelector)?void 0:a.call(n,rH))&&setTimeout(()=>{let n=r$();t.track("Dialog Opened",{dialog_title:n})},50)}})});return n.observe(document.body,{childList:!0,subtree:!0}),()=>{n.disconnect()}}(t),Promise.resolve()),execute:async t=>{if("u"<typeof window||"u"<typeof document)return t;let n=rU.get(),i=(null==n?void 0:n.dialogTitle)??r$();return i?{...t,event_properties:{...t.event_properties,dialog_title:i}}:t},teardown:async()=>(n&&n(),i&&i(),rU.clear(),Promise.resolve())})),window.addEventListener("pagehide",()=>{s8.client.setTransport("beacon"),s8.flush()}),document.addEventListener("visibilitychange",()=>{"hidden"===document.visibilityState&&(s8.client.setTransport("beacon"),s8.flush())}),s8.client.add((a="dev_",{name:"environment-plugin",type:"enrichment",setup:async()=>{},execute:async t=>{let n=t.event_type;return t}}))}Event classes for the wallet actions named in the claim
ui.jsclass sF{event_properties;event_type="exported account keys";constructor(t){this.event_properties=t,this.event_properties=t}}class sq{event_properties;event_type="opened application";constructor(t){this.event_properties=t,this.event_properties=t}}class sU{event_properties;event_type="opened link";constructor(t){this.event_properties=t,this.event_properties=t}}class sV{event_properties;event_type="opened transaction";constructor(t){this.event_properties=t,this.event_properties=t}}class sH{event_properties;event_type="pinned coin";constructor(t){this.event_properties=t,this.event_properties=t}}class s${event_type="renamed account"}class sK{event_type="reset wallet"}class sG{event_properties;event_type="responded to connection request";constructor(t){this.event_properties=t,this.event_properties=t}}class sW{event_properties;event_type="responded to transaction request";constructor(t){this.event_properties=t,this.event_properties=t}}class sY{event_properties;event_type="selected coin";constructor(t){this.event_properties=t,this.event_properties=t}}class sJ{event_properties;event_type="selected validator";constructor(t){this.event_properties=t,this.event_properties=t}}class sX{event_properties;event_type="sent coins";constructor(t){this.event_properties=t,this.event_properties=t}}class sZ{event_properties;event_type="sent collectible";constructor(t){this.event_properties=t,this.event_properties=t}}class sQ{event_properties;event_type="staked IOTA";constructor(t){this.event_properties=t,this.event_properties=t}}class s0{event_properties;event_type="started dapp connection";constructor(t){this.event_properties=t,this.event_properties=t}}Wallet-action call sites and concrete event properties
ui.jsonClick:function(){let n=null==t?void 0:t.type;n&&s8.exportedAccountKeys({accountType:qJ[n]}),m(`/accounts/export/${t.id}`)}(0,dg.useEffect)(()=>{if(s){let t=lo(s.name,s.origin);s8.startedDappConnection({applicationName:t,applicationUrl:s.origin})}},[s])onSuccess:t=>(f.invalidateQueries({queryKey:["get-coins"]}),f.invalidateQueries({queryKey:["coin-balance"]}),s8.sentCoins({coinType:g,amount:Number(x.values.amount)}),u(`/receipt?txdigest=${encodeURIComponent(t.digest)}&from=transactions`))onSubmit:async n=>{if(!p){if(n&&v)return void d(!0);await l(Cy({approved:n,txRequestID:t.id,signer:s})),eiw.includes(t.origin)||s8.respondedToTransactionRequest({applicationUrl:t.origin,approvedTransaction:n,receivedFailureWarning:!1})}}onResponse:async n=>{await l(Cy({approved:n,txRequestID:t.id,signer:s})),s8.respondedToTransactionRequest({applicationUrl:t.origin,approvedTransaction:n,receivedFailureWarning:!0}),d(!1)}External analytics destination
- api.eu.amplitude.com
Amplitude EU analytics ingestion receives the wallet-action events over HTTPS.
When this fires
When a batch threshold is hit · flushes at 5 queued events
The extension is configured to flush analytics quickly after activity, with a one-second flush interval and a queue size of five events.
Where it sends data
Destinations our analysis observed IOTA Wallet contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.
- api.eu.amplitude.com
IOTA Wallet sends data to api.eu.amplitude.com. 8 other extensions we have analyzed send data here.
