This the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

@platform Additional Resources

All the resources you will need for developing on the @platform

1 - The @client/AtClient SDK Cookbook

This cookbook contains recipes that demonstrate how to solve common problems while writing apps that implement the @protocol. Each recipe is self-contained and can be used as a reference to help you build up an application.

The Verb tree

Before we look at some of the sample code, the verb tree gives you a big picture of all of the verbs and what can be executed where.

alt_text

1. Scan

The scan verb is used to scan the available @ addresses for you either at the public level or all authorized data once the pol process has been completed. This allows addresses to be discovered and perhaps be harvested so if an address has a _ character as its first character then it is omitted from the scan list although it can still be looked up if known. The following example shows just that.

Following are the steps to run the scan verb using the @Client SDK

  1. Get an instance of AtClient
  2. Execute the scan verb using the AtClient

1.1 Get an instance of AtClient

To get an instance of the AtClient by calling the getClient method on the Client Impl class.

import 'package:at_client/at_client.dart';
import 'package:at_client/src/client/at_client_impl.dart';

void main() async  {
  
  // Construct  AtClientPreference
  var preference = AtClientPreference();
  preference.hiveStoragePath = '/hive/storage/path';
  preference.commitLogPath = '/commit/log/path';
  // Namespace is mandatory to be passed. E.g me, buzz, etc.,
  await AtClientImpl.createClient('@bob','me', preference);
  var atClient = await AtClientImpl.getClient('@bob');
}

1.2 Execute the scan verb using @AtClient

a.Simple Scan - Returns all keys
// Get an instance of AtClient for @bob
var atClient = await AtClientImpl.getClient('@bob);
// Scans keys stored in app storage
await atClient.getKeys();
b.Scan keys matching a regular expression
// Get an instance of AtClient for @bob
var atClient = await AtClientImpl.getClient('@bob);
// Scans keys in .me namespace
await atClient.getKeys(regex:'.me');
c.Scan keys shared with another atSign
// Get an instance of AtClient for @bob
var atClient = await AtClientImpl.getClient('@bob);
// Scans keys shared with @alice
await atClient.getKeys(sharedWith:'alice');
d.Scan keys shared by another atSign
// Get an instance of AtClient for @bob
var atClient = await AtClientImpl.getClient('@bob);
// Scans keys shared by @alice. This performs authenticated scan on @alice's secondary.
await atClient.getKeys(sharedBy:'alice');

2. Update

Update verb used to add entries in the @server. @signs have to be authenticated for one to run the update verb on the @server.

Following are the steps to run the scan verb using the @Client SDK

  1. Get an instance of AtClient
  2. Execute the update verb using the AtClient

2.1 Get an instance of AtClient

To get an instance of the AtClient by calling the getClient method on the AtClientImpl class.

import 'package:at_client/at_client.dart';
import 'package:at_client/src/client/at_client_impl.dart';

void main() async  {
  
  // Construct  AtClientPreference
  var preference = AtClientPreference();
  preference.hiveStoragePath = '/hive/storage/path';
  preference.commitLogPath = '/commit/log/path';
  //create atClient
  var atClient = await AtClientImpl.createClient('@bob', 'me', preference);
}

2.2 Execute the update verb using AtClient

// Get an instance of AtClient for @bob
var atClient = await AtClientImpl.getClient('@bob');
// create phoneKey
var phoneKey = AtKey()..key = 'phone';
// Update a phone number visible only to @bob
await atClient.put(phoneKey, ''+1-123-4567');
// create emailKey
var emailKey = AtKey()..key = 'email'
                      ..sharedWith = '@alice';
// Update an email visible only to @alice
await atClient.put(emailKey, 'bob@atsign.com');
// Update an email visible only to everyone
// create metadata with isPublic true
var metadata = Metadata()..isPublic=true;
// create emailKey and update metadata
var emailKey = AtKey()..key = 'email'
                      ..metadata = metadata;
await atClient.put(emailKey, 'bob@gmail.com');
// Update a location that expires in 10 minutes
 var metadata = Metadata()..ttl=600000;
var locationKey = AtKey()..key = 'current_location'
                      ..metadata = metadata;
await atClient.put(locationKey, 'https://goo.gl/maps/Trs5Dao562tLFK5Q9');

3. Lookup

The lookup verb is used to lookup a value on a @server of another @sign. The following demonstrates the use of lookup verb.

Following are the steps to run the scan verb using the @Client SDK

3.1 Get an instance of AtClient

To get an instance of the AtClient by calling the getClient method on the AtClientImpl class.

import 'package:at_client/at_client.dart';
import 'package:at_client/src/client/at_client_impl.dart';

void main() async  {
  
  // Construct  AtClientPreference
  var preference = AtClientPreference();
  // Get 
  var atClient = await AtClientImpl.createClient('@bob', 'me', preference);
}

3.2 Execute the lookup verb using AtClient

// Get an instance of AtClient for @bob
var atClient = await AtClientImpl.getClient('@bob');
// Look up phone number sharedBy @alice
//lookup:phone.me@alice
var atKey = AtKey()..key = 'phone'
                   ..sharedBy = '@alice';
await atClient.get(atKey);

4. Plookup

The plookup verb is used to lookup a public value on a @server of another @sign if the client is authenticated. Plookup verb can only be executed on a remote @server. The following demonstrates the use of plookup verb.

Following are the steps to run the scan verb using the @Client SDK

4.1 Get an instance of AtClient

To get an instance of the AtClient by calling the getClient method on the AtClientImpl class.

import 'package:at_client/at_client.dart';
import 'package:at_client/src/client/at_client_impl.dart';

void main() async  {
  
  // Construct  AtClientPreference
  var preference = AtClientPreference();
  //Get 
  var atClient = await AtClientImpl.createClient('@bob', 'me', preference);
}

4.2 Execute the plookup verb using AtClient

// Get an instance of AtClient for @bob
var atClient = await AtClientImpl.getClient('@bob');
// plookup public phone number of @alice
var metadata = Metadata()..isPublic=true;
var publicPhoneKey = AtKey()..key = 'phone'
                            ..sharedBy = '@alice'
                            ..metadata = metadata;
await atClient.get(publicPhoneKey);

5. Llookup

The llookup verb is used to lookup a value on a local @server storage of current @sign. The following demonstrates the use of llookup verb.

5.1 Get an instance of AtClient

To get an instance of the AtClient by calling the getClient method on the AtClientImpl class.

import 'package:at_client/at_client.dart';
import 'package:at_client/src/client/at_client_impl.dart';

void main() async  {
  
  // Construct  AtClientPreference
  var preference = AtClientPreference();
  preference.hiveStoragePath = '/hive/storage/path';
  preference.commitLogPath = '/commit/log/path';
  //Get 
  var atClient = await AtClientImpl.createClient('@bob', 'me', preference);
}

5.2 Execute the llookup verb using AtClient

// Get an instance of AtClient for @bob
var atClient = await AtClientImpl.getClient('@bob');
// Local lookup a self key e.g @bob:email.me@bob
var privateEmailKey = AtKey()
 ..key = 'email'
 ..sharedWith = '@bob';
var alicePrivateEmail = await atClient.get(privateEmailKey);
// Local lookup phone shared with @alice e.g @alice:email.me@bob
var phoneKey = AtKey()
 ..key = 'phone'
 ..sharedWith = '@alice';
await atClient.get(phoneKey);
// Local lookup a public key 
var metadata = Metadata()..isPublic=true;
var firstnameKey = AtKey()
 ..key = 'firstname'
 ..metadata = metadata;
await atClient.get(firstnameKey);
// Local lookup a key ignoring namespace
var metadata = Metadata()..namespaceAware=false;
var firstnameKey = AtKey()
 ..key = 'firstname'
 ..metadata = metadata;
 await atClient.get(firstnameKey);

6. Delete

The “delete” verb is used for deleting @addresses.

Following are the steps to run the scan verb using the @Client SDK

6.1 Get an instance of AtClient

To get an instance of the AtClient by calling the getClient method on the AtClientImpl class.

import 'package:at_client/at_client.dart';
import 'package:at_client/src/client/at_client_impl.dart';

void main() async  {
  
  // Construct  AtClientPreference
  var preference = AtClientPreference();
  preference.hiveStoragePath = '/hive/storage/path';
  preference.commitLogPath = '/commit/log/path';
  // create AtClient 
  var atClient = await AtClientImpl.createClient('@bob', 'me', preference);
}

6.2 Execute the delete verb using AtClient

// Get an instance of AtClient for @bob
var atClient = await AtClientImpl.getClient('@bob');
// delete self key e.g @bob:phone.me@bob
var phoneKey = AtKey()..key = 'phone'
                      ..sharedWith = '@bob';
await atClient.delete(phoneKey);
// delete email shared with @alice e.g @alice:phone.me@bob
var phoneKey = AtKey()..key = 'phone'
                      ..sharedWith = '@alice';
await atClient.delete(phoneKey);

// delete a public key e.g public:phone.me@bob
var metadata = Metadata()..isPublic=true;
var phoneKey = AtKey()
 ..key = 'phone'
 ..metadata = metadata;
await atClient.delete(phoneKey);

7. Stats

The “stats” verb is used to get certain predefined statistics from the @server.

7.1 Get an instance of AtClient

To get an instance of the AtClient by calling the getClient method on the AtClientImpl class.

import 'package:at_client/at_client.dart';
import 'package:at_client/src/client/at_client_impl.dart';

void main() async  {
  
  // Construct  AtClientPreference
  var preference = AtClientPreference();
  preference.hiveStoragePath = '/hive/storage/path';
  preference.commitLogPath = '/commit/log/path';
  // Get 
  var atClient = await AtClientImpl.createClient('@bob', 'me', preference);
}

7.2 Execute the stats verb using AtClient

// Get an instance of AtClient for @bob
var atClient = await AtClientImpl.getClient('@bob');
// Execute the verb e.g stats:1,stats:1,2 etc.,
// You can use stats number from 1 to 10
// If you want to request multiple types use as , separated values
// Ex: stats:1,2,5
await atClient.getRemoteSecondary().executeCommand('stats:1');

8. Config

The “config” verb is used to configure block list entries in the @server. If an @sign is added to the block list then connections to the @server will not be accepted.

Following are the steps to run the scan verb using the @Client SDK

  1. Get an instance of AtClient
  2. Set up a ConfigVerbBuilder & execute the verb using the AtClient

8.1 Get an instance of AtClient

To get an instance of the AtClient by calling the getClient method on the AtClientImpl class.

import 'package:at_client/at_client.dart';
import 'package:at_client/src/client/at_client_impl.dart';

void main() async  {
  
  // Construct  AtClientPreference
  var preference = AtClientPreference();
  preference.hiveStoragePath = '/hive/storage/path';
  preference.commitLogPath = '/commit/log/path';
  // Get 
  var atClient = await AtClientImpl.getClient('@bob', preference);
}

8.2 Set up a ConfigVerbBuilder & execute the verb using the AtClient

// Get an instance of AtClient for @bob
var atClient = await AtClientImpl.getClient('@bob, AtClientPreference());
var builder = ConfigVerbBuilder()..block = '@rachel';
// Execute the verb
await atClient.getLocalSecondary().executeVerb(builder);

9. Notify

The “notify” verb is used to notify another @server of change related to a @address.

Following are the steps to run the notify verb using the @Client SDK

  1. Get an instance of AtClient
  2. Set up a NotifyVerbBuilder
  3. Execute the scan using the AtClient

9.1 Get an instance of AtClient

To get an instance of the AtClient by calling the getClient method on the AtClientImpl class.

import 'package:at_client/at_client.dart';
import 'package:at_client/src/client/at_client_impl.dart';

void main() async  {
  
  // Construct  AtClientPreference
  var preference = AtClientPreference();
  preference.hiveStoragePath = '/hive/storage/path';
  preference.commitLogPath = '/commit/log/path';
  // Get 
  var atClient = await AtClientImpl.getClient('@bob');
}

9.2 Execute the notify verb using AtClient

// Create Atclient Instance
await AtClientImpl.createClient('')
// Get an instance of AtClient for @bob
var atClient = await AtClientImpl.getClient('@bob);
var atKey = AtKey()
..key = 'phone@bob'
..sharedWith = '@alice'
..sharedBy = '@bob'
// Execute the verb
await atClient.notify(atKey, '+1 987 986 2233', OperationEnum.update);
// Sending Notification with Notification Strategy 'ALL'
await atClient.notify(atKey, '+1 987 986 2233', OperationEnum.update, 
                      priority: PriorityEnum.low,
                      strategy: StrategyEnum.all);

// Sending Notification with Notification Strategy 'Latest N'
await atClient.notify(atKey, '+1 987 986 2233', OperationEnum.update, 
                      priority: PriorityEnum.high,
                      strategy: StrategyEnum.latest,
                      latestN:3,  
                      Notifier: 'wavi');                                               

9.3 Execute the notify status verb using AtClient

// Create Atclient Instance
await AtClientImpl.createClient('')
// Get an instance of AtClient for @bob
var atClient = await AtClientImpl.getClient('@bob);
var atKey = AtKey()
..key = 'phone@bob'
..sharedWith = '@alice'
..sharedBy = '@bob'
// Execute the notify verb
var notiticationId = await atClient.notify(atKey, '+1 987 986 2233', OperationEnum.update);
// get notification status of the above notificationId
var status = await atClient.notifyStatus(notificationId);                                              

10. Monitor

The “monitor” verb is used to stream incoming notifications from the @server to @Client.

Following are the steps to run the notify verb using the @Client SDK

  1. Get an instance of AtClient
  2. Execute the monitor using the AtClient

10.1 Get an instance of AtClient

To get an instance of the AtClient by calling the getClient method on the AtClientImpl class.

import 'package:at_client/at_client.dart';
import 'package:at_client/src/client/at_client_impl.dart';

void main() async  {
  
  // Construct  AtClientPreference
  var preference = AtClientPreference();
  preference.hiveStoragePath = '/hive/storage/path';
  preference.commitLogPath = '/commit/log/path';
  // Get 
  var atClient = await AtClientImpl.getClient('@bob', preference);
}

10.2 Execute the monitor verb using AtClient

// Get an instance of AtClient for @bob
var atClient = await AtClientImpl.getClient('@bob');
var builder = MonitorVerbBuilder();
// Execute the verb
await atClient.startMonitor(<privateKey>,<NotificationCallback>);

//Using Regex on Monitor verb
// Get an instance of AtClient for @bob
var atClient = await AtClientImpl.getClient('@bob');
var builder = MonitorVerbBuilder();
// Execute the verb
await atClient.startMonitor(<privateKey>,<NotificationCallback>,regex: '.wavi');

Verb Parameter Reference

required optional’*

VerbParameters
fromatSign* - @ sign you claim to be
cramdigest* - SHA512 digest
pkamsignature* - Signed challenge
polNA
scanforAtSign - Scans the keys shared by forAtSign

regex - Regex to which the @addresses has to be matched to be returned as a result

updatettl - Time to live in milliseconds. Value for the key won't be available after the ttl’

ttb - Time to birth in milliseconds. Value for the key will be available after the ttb’

Scope - Public vs Private

forAtSign* - For whom the value is being set

atKey* - Name of the @address

value* - Value for the @address

lookupatKey* - Name of the @address

atSign* - @ signs namespace

llookupatKey* - Name of the @address

atSign* - @ signs namespace

plookupatKey* - Name of the @address

atSign* - @ signs namespace

deleteatKey* - Name of the @address
statsstatId - Id’s of the statistics to display
configwhatToConfig* - Thing to configure

configValue* - Value of the thing to configure

notifyforAtSign* - @sign to notify

key* - Key to which the change has happened

change* - Change it self

monitorregex - Regex that needs to be matched for the value to be monitored

2 - The @platform Glossary of Terms

Definitions of terms and acryonms often used with the @platform

@platform :

The @platform is an open development platform for developers who want to create applications that give people full control of their digital selves. The platform is based on the @protocol - a network protocol for the secure exchange of information only between known entities. It uses a unique identifier called an @sign that, combined with the @platform (which is based on the @protocol), allows people the freedom to share, withhold, or retract their information at will with minimal effort, and the developer no longer has to bear the cost and risk of storing and managing people’s personal data.

@protocol :

The @protocol is the underlying network protocol used by the @platform.The @protocol’s objective is to provide end-to-end encrypted data transfer between two known @signs, but also provides access to publicly available data that is cryptographically signed by the creating @sign.

@sign

Each participant in the @protocol has a unique identifier known as an @sign. @sign’s are centrally registered and the rest of the infrastructure is fully distributed.Every @sign has a unique secondary server microservice that is accessible on the Internet via a unique Fully Qualified Domain Name (FQDN) and TCP/IP port number and Secure Sockets Layer (SSL) certificate.

root server :

The root servers are the only centralized part of the @protocol and are centralized to provide a single namespace and a globally dependable platform. No data beyond the @sign and responding authoritative secondary server is held on the root servers. This information is considered public, and no authentication is required to look up the secondary server for a particular @sign.

secondary server :

Secondary servers provide the second tier of the @protocol architecture, and are responsible for answering lookups for specific @signs. Secondary servers are generally deployed as microservices running on orchestrators such as Docker Swarm or Kubernetes, but can also run as standalone executables. Secondary servers have to be uniquely Internet addressable through use of an FQDN & Port pair that can be translated via DNS to a unique IP & Port.

I remember seeing The @ Company on a flutter event page for the first time and being immediately captivated by its concept, eventually attending all meetings and workshops despite the time difference.

@xavierchanth
I started out as an @ppathon participant, and worked on my app, @famiy, which is still in production. The End-to-End Encryption and data ownership is the highlight for me. The biggest concern within a family is everything can be extremely private and no one from outside that family should be able to see that information. This is already taken care of for me on the @platform.

@kudakwashe
I remember seeing The @ Company on a flutter event page for the first time and being immediately captivated by its concept, eventually attending all meetings and workshops despite the time difference.