Skip to main content
How to use ODIS to query the on-chain identifier given a phone number.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2! Some documentation may be outdated as updates are in progress. If you encounter issues, please file a bug report.For the most up-to-date information, refer to our Celo L2 documentation.

What is ODIS?

One of Celo’s key features is the ability to associate a phone number to a Celo address. This provides a convenient payment experience for Celo users. To map a phone number to an address, the on-chain identifier for a given phone number must first be retrieved. With this identifier, the address can be looked up on-chain.
ODIS requests are rate-limited based on transaction history and balance. Ensure the account that is performing the queries has a balance and has performed transactions on the network. If an out of quota error is hit, this indicates that more transactions need to be sent from the querying account.
The main ODIS method is getObfuscatedIdentifier, which queries and computes the on-chain identifier for an off-chain identifier such as a phone number.
See this overview document for more details on ODIS.

Authentication

Both methods require authentication to the ODIS server, which can be performed by either the main wallet key or the data-encryption key (DEK) associated with the wallet key. This is managed by AuthSigner, which can be either a WalletKeySigner for a wallet key or an EncryptionKeySigner for the DEK. The DEK method is preferred, since it doesn’t require the user to access the same key that manages their funds. You can learn more about DEK here. You may use the EncryptionKeySigner for your AuthSigner by passing in the raw private key:
const authSigner: AuthSigner = {
  authenticationMethod: OdisUtils.Query.AuthenticationMethod.ENCRYPTION_KEY,
  rawKey: privateDataKey,
};
Alternatively, you may use the WalletKeySigner by passing in a contractkit instance with the account unlocked:
const authSigner: AuthSigner = {
  authenticationMethod: OdisUtils.Query.AuthenticationMethod.WALLET_KEY,
  contractKit,
};

Service Context

The ServiceContext object provides the ODIS endpoint URL and the ODIS public key (same as above).
const serviceContext: ServiceContext = {
  odisUrl,
  odisPubKey,
};
The ODIS endpoint URL for each environment can be found here: The ODIS public key for each environment can be found here:
EnvironmentKey
Alfajores Staging7FsWGsFnmVvRfMDpzz95Np76wf/1sPaK0Og9yiB+P8QbjiC8FV67NBans9hzZEkBaQMhiapzgMR6CkZIZPvgwQboAxl65JWRZecGe5V3XO4sdKeNemdAZ2TzQuWkuZoA
AlfajoreskPoRxWdEdZ/Nd3uQnp3FJFs54zuiS+ksqvOm9x8vY6KHPG8jrfqysvIRU0wtqYsBKA7SoAsICMBv8C/Fb2ZpDOqhSqvr/sZbZoHmQfvbqrzbtDIPvUIrHgRS0ydJCMsA
MainnetFvreHfLmhBjwxHxsxeyrcOLtSonC9j7K3WrS4QapYsQH6LdaDTaNGmnlQMfFY04Bp/K4wAvqQwO9/bqPVCKf8Ze8OZo8Frmog4JY4xAiwrsqOXxug11+htjEe1pj4uMA

Query phone number identifier

This call consumes quota. When the user runs out of quota, it’s recommended to prompt the user to “purchase” more quota by sending a transaction to themselves. This method returns the pepper retrieved from the service as well as the computed on-chain identifier that is generated using this pepper and the phone number.

BLS Blinding Client

It’s important for user privacy that the ODIS servers don’t have the ability to view the raw phone number. Before making the request, the library first blinds the phone number using a BLS library. This prevents ODIS from seeing the phone number while still making the resulting signature recoverable to the original phone number. The blinding client is written in Rust and compiled to WebAssembly. The SDK ships a WasmBlsBlindingClient. If you don’t pass a blinding client, getObfuscatedIdentifier defaults to it:
const blsBlindingClient = new WasmBlsBlindingClient(odisPubKey);
WasmBlsBlindingClient only runs in a Node.js environment: its constructor throws in React Native and in the browser. For browser or React Native runtimes, pass your own web blinding client. See the example web blinding client in the social-connect repo. Now you’re ready to get the on-chain identifier. OdisUtils.Identifier.getObfuscatedIdentifier documentation can be found here. The response will be an IdentifierHashDetails object with the plaintext identifier, the on-chain identifier (obfuscatedIdentifier), and the pepper.
The older OdisUtils.PhoneNumberIdentifier.getPhoneNumberIdentifier (which returns a phoneHash) is deprecated in favor of getObfuscatedIdentifier.
You can view an example of this call in the SocialConnect Twitter sample app.