GithubHelp home page GithubHelp logo

coinbase / coinbase-wallet-sdk Goto Github PK

View Code? Open in Web Editor NEW
1.3K 1.3K 487.0 24.5 MB

An open protocol that lets users connect their mobile wallets to your DApp

Home Page: https://coinbase.github.io/coinbase-wallet-sdk/

License: MIT License

TypeScript 90.32% JavaScript 6.72% SCSS 2.58% Shell 0.38%
coinbase ethereum ethereum-wallet

coinbase-wallet-sdk's People

Contributors

aarsenault avatar amitgoelny avatar andrewgold avatar arjun-dureja avatar bangtoven avatar brendanww avatar brianchitester avatar cb-jake avatar cb-kfroemming avatar cb-pedro-rosario avatar dependabot[bot] avatar erin-at-work avatar fan-zhang-sv avatar gareys-cb avatar gbarr01 avatar github-actions[bot] avatar hieronymus777 avatar jakepanitz avatar jeongmincho avatar ljharb avatar lukasrosario avatar natereiners avatar pedrorosarioo avatar petejkim avatar ryantimesten avatar shanamatthews avatar spencerstock avatar vishnumad avatar vladimirmikulic avatar willn-cb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

coinbase-wallet-sdk's Issues

Coinbase wallet: window.walletLinkExtension.setProvider info is not defined

Hi!

Problem

I have updated the package to ^2.1.0 and when I open my app in coinbase wallet I'm getting this error:

window.walletLinkExtension.setProvider info is not defined

I believe it's from this line: https://github.com/walletlink/walletlink/blob/d69239381ebe9a5ca30f0f04304c9adc0218ed8a/js/src/WalletLink.ts#L109

I tried inspecting the walletLinkExtension object and it seems to only have these keys:

_events,_eventsCount,_maxListeners,isCipher,isToshi,isCoinbaseWallet,_filterPolyfill,_subscriptionManager,appName,appVersion,_address,_chainId

Coinbase wallet version:

24.5.495 on iOS

Module Export Issue on Docker Build

Hi,

I'm running into this error when trying to use docker to run the build for an app that has walletlink as a module.

sitemap_prod-66_xml_—_researchhub-web

Context

  • node v13.7.0

  • npm v6.13.6

I've tried removing and adding walletlink back as a dependecy. It builds fine locally, but I still run into this error when building with Docker.

connector modal not opening on my setup. works on codesandbox

walletlink connector modal doesnt open up on my local project, but works with the same version here: https://codesandbox.io/s/github/NoahZinsmeister/web3-react/tree/v6/example

after digging deep, i found out that the module (url) within the file dist/relay/WalletLinkRelay.js, thats getting resolved here doesnt have the .default field, and hence it gracefully throws an error at that point. once i remove the default n then start up my app, the modal works fine.
image

apparently all other dependency packages work fine, except for this.

i use typescript (tried with 3 and 4) and the project is based out of preact-cli. also tried with the same tsconfig that's found in this project, still the same. any clue?

Walletlink + etherjs?

Is there any plans to support etherjs? it's a much faster and lighter library than web3...

walletlink how to integration

http://www.helloaltcoins.com/#!/trade/BCT-ETH
i have add walletlink code in index.html (main page )
i have already install

With Yarn

yarn add walletlink

With NPM

npm install walletlink

this command
but does not work
please have look

<script> // TypeScript import WalletLink from "walletlink" import Web3 from "web3" const APP_NAME = "helloaltcoins" const APP_LOGO_URL = "http://www.helloaltcoins.com/images/logo256.png" const ETH_JSONRPC_URL = "https://mainnet.infura.io/v3/261afee99a634b7586757e162f6b38cf" const CHAIN_ID = 1 // Initialize WalletLink export const WalletLink = new WalletLink({ appName: APP_NAME, appLogoUrl: APP_LOGO_URL }) // Initialize a Web3 Provider object export const ethereum = walletLink.makeWeb3Provider(ETH_JSONRPC_URL, CHAIN_ID) // Initialize a Web3 object export const web3 = new Web3(ethereum as any) // Optionally, have the default account be set automatically when available ethereum.on("accountsChanged", (accounts: string[]) => { web3.eth.defaultAccount = accounts[0] }) web3.eth.defaultAccount = web3.eth.accounts[0] // Use eth_RequestAccounts ethereum.send("eth_requestAccounts").then((accounts: string[]) => { console.log(`User's address is ${accounts[0]}`) }) // Alternatively, you can use ethereum.enable() ethereum.enable().then((accounts: string[]) => { console.log(`User's address is ${accounts[0]}`) }) </script>

can you please enplane proper solution and provide proper code included wlletlink button
thanks

[UX] Don't force user to leave Dapp on tx

Current behavior

When I submit a transaction, I am forced to leave the dapp browser. Likely this is leftover from early dapp days, when most dapps did not track transaction progress.

Expected behavior

Make the default behavior to stay on the dapp browser page. Many dapps track tx progress now, and its very bad experience to "rip" them away.

Wrong signature when signing message?

I'm using Walletlink in https://demo.snapshot.page to sign message but for some reason the signature created by is diffent than Metamask, i canot validate the signed message if it come from Walletlink. Any idea whats wrong? Do you have existing app using signing message ability?

iOS non-compatible

I have a coinbase wallet and a metamask wallet on this iOS device. I can’t give dydx permission from my browser. Have tried in Chrome, Safari, and Brave.

'disconnect' Event Listener

As far as I can tell, there is no way to know in a Dapp if the user has disconnected the session via the advanced settings in the Coinbase wallet app. It would be great to be able to subscribe to a disconnection event so that the dapp can handle it:

provider.on('disconnect', () => {
// handle disconnect
})

Currently, if a user does disconnect from a session, and then if the Dapp tries to initiate a transaction, it will show the popup with a pending state. After a certain amount of time it will give the option to reconnect. When that is clicked, the connection modal pops up, but then the page automatically refreshes. Is this intended behavior?

Support for mobile deep linking

Issue

The current implementation requires two devices- desktop and mobile. The only alternative is to use the built-in browser in the Coinbase Wallet. This creates a bad user experience for these reasons:

  • User is much more likely to navigate to a dapp from their default mobile browser, not from the Coinbase Wallet browser. Having to copy/paste a URL into Coinbase Wallet browser is not a good experience.
  • Progressive Web Apps are not possible, since a dapp can only be opened in Coinbase Wallet browser.

Potential solution

Support should be added for deep linking / universal linking

  • If desktop, show the standard QR prompt
  • If mobile, show a button to open Coinbase Wallet using deep linking

WalletConnect has already implemented this feature (see screenshot below). Their documentation only includes mobile linking for native apps. However it works for browser-based apps as well, which is what I am suggesting here.

Screenshot_20200708-122356

Discussion

  1. Adding this feature will likely mean less users in the Coinbase Wallet browser initially, but it doesn't necessarily mean they won't use the browser at all, eg. to discover new apps. Despite this, it doesn't appear you are doing any sponsored promotions in the browser. Therefore, I don't think that this will have any financial impact on the company. However this isn't for me to decide.

  2. Progressive Web Apps are extremely important for dapp developers. They are the only "safe space" we have for delivering native-like experiences. In my opinion, its not worth the effort to build for Google and Apple stores, given harsh treatment against crypto apps (even reputable ones like MetaMask). Forcing users to use the built-in wallet browser is a slap in the face for dapp developers.

An accessor cannot be declared in an ambient context

Hi. When I try to use it in my Angular v6 project I'm getting this. Is there any way to fix it?

ERROR in node_modules/walletlink/dist/provider/WalletLinkProvider.d.ts(17,9): error TS1086: An accessor cannot be declared in an ambient context.
node_modules/walletlink/dist/provider/WalletLinkProvider.d.ts(18,9): error TS1086: An accessor cannot be declared in an ambient context.
node_modules/walletlink/dist/provider/WalletLinkProvider.d.ts(19,9): error TS1086: An accessor cannot be declared in an ambient context.
node_modules/walletlink/dist/provider/WalletLinkProvider.d.ts(20,9): error TS1086: An accessor cannot be declared in an ambient context.
node_modules/walletlink/dist/provider/WalletLinkProvider.d.ts(21,9): error TS1086: An accessor cannot be declared in an ambient context.

CORS errros

Hi,

Trying to use WalletLink to connect to oasis.app to manage a CDP using Coinbase mobile wallet. Seeing the following errors:

Is this something I can fix or is it on the Oasis developers?

Fetch API cannot load wss://mainnet.infura.io/ws/v3/58073b4a32df4105906c702f167b91d2. URL scheme must be "http" or "https" for CORS request.

backend.js:6 TypeError: Failed to fetch

Remove the need for Node.js polyfills

WalletLink relies on native Node modules, which means that bundlers are responsible to provide polyfills for these modules. This can be problematic for several reasons:

  • Some bundlers don’t provide polyfills by default (e.g. Webpack 5, Snowpack).
  • These polyfills can be huge (e.g. with crypto-browserify), and are often not using the native browser APIs like window.crypto.
  • These polyfills can be implemented in various ways, which impacts WalletLink robustness, stability and security for end users.

If the intent is to maintain a compatibility between Node and browsers, I would suggest to add another entry point for it (e.g. src/index-browser.ts => dist/index-browser.js). It would make it possible to provide different implementations between Node and the browser when needed.

Here is a list of native Node modules used by WalletLink, and suggestions on what could be done to support browser environments.

@petejkim let me know what you think! 🙂

url

The url module is only used once to parse a URL. This one is easy, as both Node and browser environments provide a globa URL object that can do the same thing without having to import any module:

const url = new URL(this.walletLinkUrl)
this.walletLinkOrigin = `${url.protocol}//${url.host}`

crypto

crypto.randomBytes()

This is used in a few places:

https://github.com/walletlink/walletlink/blob/ffc86286a1692334523783257d1da68f11a0043b/js/src/relay/WalletLinkRelay.ts#L303

https://github.com/walletlink/walletlink/blob/ffc86286a1692334523783257d1da68f11a0043b/js/src/relay/Session.ts#L28-L29

https://github.com/walletlink/walletlink/blob/ffc86286a1692334523783257d1da68f11a0043b/js/src/relay/aes256gcm.ts#L8

As an example, here is a Node-only function that could be used in these cases:

const crypto = require('crypto')

function randomBytesHex(length) {
  return crypto.randomBytes(length).toString("hex")
}

And here is how we could implement a browser equivalent:

function randomBytesHex(length) {
  return uint8ArrayToHex(crypto.getRandomValues(new Uint8Array(length)))
}

// This function is needed because browser’s crypto.getRandomValues()
// return a Uint8Array while Node’s crypto.randomBytes() returns a Stream.
function uint8ArrayToHex(value) {
  return [...value].map(b => b.toString(16).padStart(2, '0')).join('')
}

Another solution could be to use the uuid module. It works in Node and browser environments, and the version 4 (random) UUID would help in cases where a unique ID of any size is needed.

crypto.createCipheriv()

This is used in the aes256gcm.ts module, to encrypt and decrypt:

https://github.com/walletlink/walletlink/blob/ffc86286a1692334523783257d1da68f11a0043b/js/src/relay/aes256gcm.ts#L9-L13

Browsers provide the window.crypto.subtle.encrypt() and window.crypto.subtle.decrypt() methods.

The AES-GCM algorithm is supported: https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt#AES-GCM

And here is an example on how to use it: https://github.com/mdn/dom-examples/blob/a7e751ff4b82cc19bd3b7451897c254ebe78ebd5/web-crypto/encrypt-decrypt/aes-gcm.js

The two APIs are quite different here, so I think it could be a good idea to provide a browser-only version of aes256gcm.ts, that would be injected from the entry point.

Another solution could be to use a module like @peculiar/webcrypto, which provides a Node polyfill for the WebCrypto API. It has a cost in terms of performances and bundle size, but it would allow to use the same API for both Node and the browser.

keccak

The keccak module already provides a version for browsers:

https://github.com/cryptocoinjs/keccak/blob/e77962484b20fe3c1ca3ddd7e3f455bb118cc545/package.json#L22-L25

The issue is that only the Node version is being used by WalletLink:

https://github.com/walletlink/walletlink/blob/ffc86286a1692334523783257d1da68f11a0043b/js/src/vendor-js/keccak/index.js

I would recommend to either move it as an external dependency (to preserve the package.json fields), or to reproduce this internally by having the browser version in src/vendor-js/keccak and import it from the WalletLink browser entry point.

unsupported methods fails violently

I noticed that some methods are not available. In particular:

  • eth_chainId
  • personal_sign
  • eth_signTypedData_v3

While I understand that not all methods are implemented (chainId is a shame, as it shouldn't be that hard to implement) ... my biggest issue is that this fails violently. I'm can't even manage to catch it! Is that a known issue?

WalletLink insert HTML outside of body

By using walletlink like this (on demand)

const WalletLink = (await import('walletlink')).default;
const walletLink = new WalletLink({ appName: '...', appLogoUrl: '...' });

It seems to insert it's style and html outside of body, which breaks stuff as it's not valid HTML.

image

Using latest [email protected]

Walletlink have to insert it's HTML & STYLE only inside of BODY. Otherwise it will produce incorrect HTML which might not work.

Add support for EIP1193 + test networks

Issue

  1. Test networks are not supported
  2. Cannot detect when the network is changed by the user (related to #39 )

Code snippet

No matter what I do, I cannot seem to unlock the wallet using any network other than mainnet (homestead). And when switch networks in the app, the function is never called, which suggests that EIP1193 hasn't been implemented.

@walletconnect/web3-provider v1.0.13
walletlink ^2.0.2
Coinbase Wallet v22.3.307

import { Web3Provider } from "@ethersproject/providers";
import WalletLink from "walletlink";

export const unlockWalletLink = async ({
  infuraKey,
  debug,
  targetNetwork,
  onNetworkChange
}) => {
  const ETH_JSONRPC_URL = `https://mainnet.infura.io/v3/${infuraKey}`;
  try {
    const walletLink = new WalletLink({
      appName: APP_NAME,
      appLogoUrl: APP_LOGO_URL,
    });
    const ethereum = walletLink.makeWeb3Provider(
      ETH_JSONRPC_URL,
      42 // targetNetwork ? getIdFromName(targetNetwork) : 1
    );
    const walletProvider = new Web3Provider(ethereum);
    const accounts = await ethereum.enable();

    // Issue #1, this is always homestead
    const network = await walletProvider.getNetwork();

    // Issue #2, onNetworkChange is never called
    walletProvider.on("chainChanged", onNetworkChange);

Discussion

EIP1193 has already been implemented in MetaMask link and WalletConnect link

This update would be really helpful for testing purposes, and I appreciate your support

Failed to subscribe to new newBlockHeaders to confirm the transaction receipts.

When I try to interact with my smart contracts and I wait the response with a promise or async , the conection web3 connected to the wallet walletlink throw this error:

image

I write a simple example, for test and appears the same error:
https://github.com/damarnez/walletlink_example

The line that we get the throw are :

await contracts.TestDani.methods.set(magicNumber).send({ from: address });

Is a simple transaction and wait the response from the chain. With others wallets works perfectly..

Feels like the problem is Infura doesn't allow newBlockHeaders by spec.https://infura.io/docs/#supported-json-rpc-methods

What can I do?

Infura : https://kovan.infura.io/v3/ ****
Web3 version : 1.2.1
WalletLink: 1.0.0

Cannot read property 'EIP712Domain' of undefined - signTypedData

Signing data worked in trustwallet, metamask, opera wallet. But not in coinbase using walletlink.

Using eth_signTypedData_v3 - when sent to coinbase wallet via walletlink the error Cannot read property 'EIP712Domain' of undefined is returned.

   const domain = [
      { name: "name", type: "string" },
      { name: "version", type: "string" },
      { name: "chainId", type: "uint256" },
      { name: "verifyingContract", type: "address" },
      { name: "salt", type: "bytes32" },
    ];
  const data = JSON.stringify({
      types: {
        EIP712Domain: domain,
        Listing: Listing,
      },
      primaryType: "Listing",
      domain: domainData,
      message: message,
    });
 
    const signedData = await new Promise((resolve, reject) => {
      web3.currentProvider.sendAsync(
        {
          method: "eth_signTypedData_v3",
          params: [account, data],
          from: account,
        },

returns the error:

web3.saga.tsx:720 TypeError: Cannot read property 'EIP712Domain' of undefined
    at Object.findTypeDependencies (index.js:149)
    at Object.encodeType (index.js:127)
    at Object.hashType (index.js:179)
    at Object.encodeData (index.js:42)
    at Object.hashStruct (index.js:168)
    at Object.hash (index.js:208)
    at Object.hashForSignTypedData_v3 (index.js:225)
    at WalletLinkProvider._eth_signTypedData_v3 (WalletLinkProvider.js:449)
    at WalletLinkProvider._handleAsynchronousMethods (WalletLinkProvider.js:235)
    at WalletLinkProvider.js:186
    at new Promise (<anonymous>)
    at WalletLinkProvider._sendRequestAsync (WalletLinkProvider.js:165)
    at WalletLinkProvider.sendAsync (WalletLinkProvider.js:112)

Yet in walletlink's code it has:

  async _eth_signTypedData_v3(params) {
        this._requireAuthorization();
        const address = util_1.ensureAddressString(params[0]);
        const typedData = params[1];
        this._ensureKnownAddress(address);
        const message = eth_eip712_util_1.default.hashForSignTypedData_v3({ data: typedData });
        const typedDataJson = JSON.stringify(typedData, null, 2);
        return this._signEthereumMessage(message, address, false, typedDataJson);
    }

web3provider has no `.on()` endpoint

web3.on is commonly used by frontend to adapt to wallet events.

It not being avaialble on walletlink breaks a lot of assumption dapps usually have about providers.

Make possibility to use own custom QR code modal window

Problem

We develop a browser extension. Usually, they consist of several parts: background, inpage script, popup etc (see the picture below).
image
We'd like to create an instance of WalletLink inside the background, but during paring there is no posibillity to show QR code to an user, because the background doesn't have a representation layer despite the fact that it has own DOM.

Possible Solution

Possibly to make a some hook, which fires in the moment of pairing.
It might look like this:

// Initialize WalletLink
const walletLink = new WalletLink({
  appName: APP_NAME,
  appLogoUrl: APP_LOGO_URL,
  darkMode: false,
  qrcode: false // disables injecting of the modal window into the DOM
})

// Subscribe to QR code displaying event
walletLink.on("display_qrcode", (url) => {
  // e.g. url = "https://www.walletlink.org/#/link?id=0000&secret=0000&server=https%3A%2F%2Fwww.walletlink.org&v=1"
  showCustomQR(url);
});

But your WallletLink instance doesn't have any subscription methods like 'on()', and it looks like such a solution doesn't fit into your architecture.
It would be great to discuss where and how is better to make such feature within your application architecture.
I could help to implement this and make a PR.

Unable to open qrmodel

Unable to open qrmodel

When user clicks walletconnect , we unable to open the qr code on popup

Retrieve user's address without infura

In my case, I need just the user address. To prevent copy/paste, i would use walletlink.

I made a prototype but with the infura limitation, I wouldn't provide my infura key on a frontend app.

Support multiple cryptocurrencies

Please add support for multiple cryptocurrencies and cryptographies. There should be support for Bitcoin, Litecoin, Ethereum and other. This would be useful because they can be used for cryptograph operations (signing).

No network checking or alerts (danger!)

Issue

Currently there is no network check when making a transaction request. This could mean losing funds (!!) for a developer who is testing using another network.

Steps to reproduce

const ETH_JSONRPC_URL = `https://mainnet.infura.io/v3/${infuraKey}`;
const CHAIN_ID = 1;
const ethereum = walletLink.makeWeb3Provider(ETH_JSONRPC_URL, CHAIN_ID);

Change your test wallet network to something besides mainnet. Then push any transaction to the wallet.

Possible solution

  • There should be some indicator that the network for the transaction is mainnet. This is only really relevant while on a testnet, so normal users would never see it,

Cash

0xf418139413ea1A3142D748469C89b0D9011BF0c2

No way to disconnect from dapp

Bug Description

No way to disconnect from the dapp or mobile iOS

Steps to Reproduce

  1. Press disconnect on CoinbaseWallet and the localStorage remains on the dapp

Expected Behavior

Disconnect after pressing disconnect.
What I really want is that there is no way to disconnect on the dapp.

WalletConnect handles it really well with a simple:

await provider.close()

This throws an error as the function does not exists.

Google tag manager: ERR_NAME_NOT_RESOLVED

Getting this ugly error message, any time I call new WalletLink . Note the tag shown here is obscured for my sake.

GET https://www.googletagmanager.com/gtag/js?id=UA-1*******net::ERR_NAME_NOT_RESOLVED

Referrer Policy: no-referrer-when-downgrade

While we are on the topic, I urge you to consider removing Google completely from this library. It's not in the ethos of the community to be using Google to track users. There are plenty of open source tools for analytics available. Personally I use https://matomo.org and it rocks!

Unable to authorize on Android

Hello 👋 !

We are attempting to add the WalletLink integration to Pool Together, however on Android after scanning the QR code it says "Authorize on Wallet App" but the authorization dialogue never appears, even after waiting a long period of time.

We tried uninstalling and reinstalling the Wallet app with no luck, as well as deleting the __WalletLink__:https://www.walletlink.org:SessionId cookie from the browser.

Also tested it out on iPhones and sometimes it does work, but the auth message can take 20 - 30 seconds to appear at times.

The specific version of our app we are using to test with is https://staging.pooltogether.us/ - You can click 'Connect Wallet' in the top-right corner to try our implementation.

Cheers, thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.