Welcome, builders ๐๐ This repo holds Dfns Typescript SDK. Useful links:
Node version 18 or greater recommended
npm i @dfns/sdk
Check out the list of all examples in /examples.
CredentialSigner
All state-changing requests made to Dfns API need to be cryptographically signed by some Credentials registered with the User / Service Account.
Note To be more precise, it's not the request itself which needs to be signed, but it's actually a "User Action Challenge" issued by Dfns which needs to be signed. As a simplification, we speak of "request signing"
This request signature is a cryptographic proof that you and only you are making the request. Without it, the request would raise an Unauthorized error.
Credentials can be one of two kinds (check our API docs Credential section for more details): WebauthN Credentials or Key Credentials. WebauthN credentials only work in the browser. Key credentials can work in the browser (BrowserKeySigner) or in node (AsymmetricKeySigner). The classes below support each one, their responsibility is to sign a challenge:
The SDK exposed in @dfns/sdk-browser
implements two classes: WebAuthnSigner
and BrowserKeySigner
.
WebAuthnSigner
is highly recommended as it is the most secure option. The private key never leaves the authenticator and is never available to the browser.
BrowserKeySigner
is disouraged as the private key lives in the browser memory. The developer needs to come up with a secure way to load and use the private key while still keeping it secure.
WebAuthnSigner
WebAuthnSigner
implements CredentialSigner
and CredentialStore
. It needs to be used client-side (on a browser, in a web-app)
import { WebAuthnSigner } from '@dfns/sdk-browser'
const webauthn = new WebAuthnSigner({ relyingParty: { id: 'acme.com', name: 'Acme' } })
BrowserKeySigner
BrowserKeySigner
implements CredentialSigner
and CredentialStore
. It needs to be used client-side (on a browser, in a web-app)
import { BrowserKeySigner } from '@dfns/sdk-browser'
const browserKey = new BrowserKeySigner({
keyPair: keyPair, // This is the keyPair object of type [CryptoKeyPair](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKeyPair). This key should be protected and loaded securely in the browser.
})
// Create the attestation object to register the credential
const attestation = await browserKey.create(challenge)
// Create the assertion object to sign a request with the credential
const assertion = await browserKey.sign(challenge)
PasskeysSigner
in @dfns/sdk-react-native
package, implements CredentialSigner
and CredentialStore
. It needs to be used client-side with the react native framework.
import { PasskeysSigner } from '@dfns/sdk-react-native'
const passkeys = new PasskeysSigner()
AsymmetricKeySigner
AsymmetricKeySigner
in @dfns/sdk-keysigner
package, implements CredentialSigner
. It needs to be used server-side. It could be used client-side, but we don't recommend it. In a browser, use BrowserKeySigner
. Any key-based crypto signing should be handled in a service worker.
import { AsymmetricKeySigner } from '@dfns/sdk-keysigner'
const keySigner = new AsymmetricKeySigner({
credId: 'X2ktMzhxaTEtZTF1bTgtOXY1cG9yY2tkZDe1dG1jYg', // Credential ID
privateKey: process.env.DFNS_PRIVATE_KEY!, // Credential private key
})
credId
: ID of the Credential registered with the auth token youโre using (Personal Access Token, or Service Account Token). In Dfns dashboard, you can find it next to your token (in Settings
> My Access Tokens
or Settings > Service Accounts
)privateKey
: private key (in .pem format) which only you have, associated with the public key you registered when you created your PAT / Service Account.DfnsApiClient
DfnsApiClient
is the main Dfns client, holding most supported functionalities of Dfns API.
It needs to be authenticated, so DfnsApiClient
needs to be passed a valid authToken
. This authToken
can be:
DfnsApiClient
also needs to be passed a CredentialSigner, in order to sign requests.
import { DfnsApiClient } from '@dfns/sdk'
const signer = ... // a Credential Signer (webauthN or key signer from section above)
const apiClient = new DfnsApiClient({
baseUrl: 'https://api.dfns.io', // base Url of DFNS API
appId: 'ap-2ng9jv-80cfc-983pop0iauf2sv8r', // ID of the Application registered with DFNS
authToken: '...', // an auth token
signer,
})
// create a wallet
const wallet = await dfns.wallets.createWallet({
body: { network: 'EthereumSepolia' }
})
// get assets in wallet
const { assets } = await dfns.wallets.getWalletAssets({ walletId: wallet.id })
DfnsDelegatedApiClient
In some configurations, you might want your server to be the one talking to Dfns "on behalf of the user", but till have the user sign all requests (on a web-app, using the WebauthN Credentials he owns). In this case, the DfnsDelegatedApiClient
can be used on your server.
The difference with the above DfnsApiClient
is:
DfnsApiClient
, all steps to sign the request are done internally.DfnsDelegatedApiClient
, the signing of the request (of the challenge, really) happens outside of it. So while the request can be conducted by the server, the signature of this request can be done by the User (on a web-app).In a way, DfnsDelegatedApiClient
"delegates" request signing outside of it. As a result:
CredentialSigner
(since signing happens outside)dfns.wallets.createWallet()
) will be splitted in two methods:dfns.wallets.createWalletInit()
: takes in the request payload, and returns a challenge that should be signed by a CredentialSigner
.dfns.wallets.createWalletComplete()
: takes in the request payload + the signed challenge, and completes the wallet creation.An example flow would look like:
createWalletInit
, and sends back the returned challenge to the use on the web-app.WebauthN
signer), and sends the signed challenge to the server.createWalletComplete
on behalf of the user.import { DfnsDelegatedApiClient } from '@dfns/sdk'
const dfnsDelegated = new DfnsDelegatedApiClient({
baseUrl: 'https://api.dfns.io', // base Url of DFNS API
appId: 'ap-2ng9jv-80cfc-983pop0iauf2sv8r', // ID of the Application registered with DFNS
authToken: userAuthToken, // Auth token of the User
})
const challenge = await dfnsDelegated.wallets.createWalletInit(payload)
// ... the server can now send this challenge to the user, so the User signs it with his credentials
// ... Later, after user sends back the signed challenge, the server can complete the request:
const wallet = await dfnsDelegated.wallets.createWalletComplete(payload, signedChallenge)
DfnsAuthenticator
In a client-side app, if you want a Dfns User to be able to login with Dfns (and get an auth token back), you might wanna use DfnsAuthenticator
:
import { DfnsAuthenticator } from '@dfns/sdk'
import { WebAuthn } from '@dfns/sdk-browser'
const dfnsAuth = new DfnsAuthenticator({
appId,
baseUrl: apiUrl,
signer: new WebAuthn({ rpId }),
})
// Since we are using a Webauthn Signer here, this will prompt the user for webauthn credentials (touch id / phone id / yubikey touch...)
const { token } = await dfnsAuth.login({ orgId, username })
BaseAuthApi
BaseAuthApi
is a Dfns client which holds some special auth-related Dfns methods (some of them are un-authenticated API endpoints for login/registration) which might get handy.
import { BaseAuthApi } from '@dfns/sdk/baseAuthApi'
BaseAuthApi.createUserActionChallenge()
BaseAuthApi.signUserActionChallenge()
BaseAuthApi.createUserLoginChallenge()
BaseAuthApi.createUserLogin()
BaseAuthApi.createUserRegistrationChallenge()
BaseAuthApi.createUserRegistration()
Integrations with other blockchain platforms to make Dapp development frictionless. More to come...
Generated using TypeDoc