Azimuth is the public-key infrastructure used for Urbit identities, deployed as smart contracts on Ethereum. For a deep dive, the official documentation has an in-depth reference.
It currently relies on events from Infura (e.g., via eth-mainnet.urbit.org), as seen in this diagram:
Ideally, this core component of the Urbit stack would not rely on centralized entities. Additionally, events are not verifiable, which defeats the purpose of certain applications that rely on them.
The problem of "getting data from Ethereum" is not unique to Urbit and plagues nearly all applications that rely on blockchain data. Users and Dapp developers either run a full archive node (tricky and expensive) or rely on centralized service providers (easy and expensive). This is one reason why Laconic created the watcher framework, which significantly reduces the cost of reading and verifying blockchain data. This framework was used to create the Azimuth Watcher, which provides a GraphQL interface for querying the Azimuth contracts' state.
The Azimuth Watcher is open source (see below) but requires good hardware. It is here hosted for your convenience:
- range can be maximum 1000 blocks
- includes full history from contract genesis
Example query from contract genesis
{
azimuthEventsInRange(fromBlockNumber:
6784880, toBlockNumber:
6785880) {
block {
hash
timestamp
}
event {
... on OwnerChangedEvent {
__typename
owner
point
}
... on ActivatedEvent {
__typename
point
}
... on SpawnedEvent {
__typename
child
}
}
contract
}
}
{
azimuthEventsInRange(fromBlockNumber:
18664121, toBlockNumber:
18664122) {
block {
hash
timestamp
}
event {
... on OwnerChangedEvent {
__typename
owner
point
}
... on ActivatedEvent {
__typename
point
}
... on SpawnedEvent {
__typename
child
}
}
contract
}
}
go to: https://azimuth.dev.vdb.to/azimuth/graphql
try:
subscription MySubscription {
onEvent {
contract
event {
... on OwnerChangedEvent {
owner
point
}
__typename
}
proof {
data
}
}
}
in, e.g., azimuth.js
:
// Reference: https://github.com/enisdenjo/graphql-ws/tree/v5.12.0#use-the-client
const { createClient } = require('graphql-ws');
const WebSocket = require('ws');
const client = createClient({
url: 'wss://azimuth.dev.vdb.to/azimuth/graphql',
webSocketImpl: WebSocket
});
// subscription
(async () => {
const onNext = (value) => {
/* handle incoming values */
console.log('Received new data:', JSON.stringify(value, null, 2));
};
let unsubscribe = () => {
/* complete the subscription */
console.log('subscription completed')
};
const query = `
subscription MySubscription {
onEvent {
contract
event {
... on OwnerChangedEvent {
owner
point
}
__typename
}
}
}
`;
try {
await new Promise((resolve, reject) => {
unsubscribe = client.subscribe(
{ query },
{
next: onNext,
error: reject,
complete: resolve,
},
);
});
} catch (err) {
console.error(err);
}
})();
then run:
node azimuth.js
example responses:
Received new data: {
"data": {
"onEvent": {
"contract": "0x223c067F8CF28ae173EE5CafEa60cA44C335fecB",
"event": {
"owner": "0xCfB830a6ffBC26e847ec40533e102528F7F9D345",
"point": "2658108823",
"__typename": "OwnerChangedEvent"
}
}
}
}
Received new data: {
"data": {
"onEvent": {
"contract": "0x223c067F8CF28ae173EE5CafEa60cA44C335fecB",
"event": {
"__typename": "BrokeContinuityEvent"
}
}
}
}
Received new data: {
"data": {
"onEvent": {
"contract": "0x223c067F8CF28ae173EE5CafEa60cA44C335fecB",
"event": {
"__typename": "ChangedKeysEvent"
}
}
}
}
This initial implementation was funded retroactively by the Urbit Foundation. Additional funding is available for a Hoon developer to integrate this source of Azimuth data as an option when running UrbitOS. Contact ~labtul-moltev if you are interested in tackling this task.