···11The zlib License
2233-Copyright (c) 2025 Jakub Suder
33+Copyright (c) 2026 Jakub Suder
4455This software is provided 'as-is', without any express or implied
66warranty. In no event will the authors be held liable for any damages
+8-4
README.md
···13131414## Installation
15151616-From the command line:
1616+To use DIDKit, you need a reasonably new version of Ruby โ it should run on Ruby 2.6 and above, although it's recommended to use a version that's still getting maintainance updates, i.e. currently 3.2+. A compatible version should be preinstalled on macOS Big Sur and above and on many Linux systems. Otherwise, you can install one using tools such as [RVM](https://rvm.io), [asdf](https://asdf-vm.com), [ruby-install](https://github.com/postmodern/ruby-install) or [ruby-build](https://github.com/rbenv/ruby-build), or `rpm` or `apt-get` on Linux (see more installation options on [ruby-lang.org](https://www.ruby-lang.org/en/downloads/)).
17171818- gem install didkit
1818+To install the gem, run in the command line:
19192020-Or, add this to your `Gemfile`:
2020+ [sudo] gem install didkit
2121+2222+Or add this to your app's `Gemfile`:
21232224 gem 'didkit', '~> 0.3'
2325···106108107109## Credits
108110109109-Copyright ยฉ 2025 Kuba Suder ([@mackuba.eu](https://bsky.app/profile/did:plc:oio4hkxaop4ao4wz2pp3f4cr)).
111111+Copyright ยฉ 2026 Kuba Suder ([@mackuba.eu](https://bsky.app/profile/did:plc:oio4hkxaop4ao4wz2pp3f4cr)).
110112111113The code is available under the terms of the [zlib license](https://choosealicense.com/licenses/zlib/) (permissive, similar to MIT).
114114+115115+Bug reports and pull requests are welcome ๐
···66require_relative 'resolver'
7788module DIDKit
99+1010+ #
1111+ # Represents a DID identifier (account on the ATProto network). This class serves as an entry
1212+ # point to various lookup helpers. For convenience it can also be accessed as just `DID` without
1313+ # the `DIDKit::` prefix.
1414+ #
1515+ # @example Resolving a handle
1616+ # did = DID.resolve_handle('bsky.app')
1717+ #
1818+919 class DID
1020 GENERIC_REGEXP = /\Adid\:\w+\:.+\z/
11211222 include Requests
13232424+ # Resolve a handle into a DID. Looks up the given ATProto domain handle using the DNS TXT method
2525+ # and the HTTP .well-known method and returns a DID if one is assigned using either of the methods.
2626+ #
2727+ # If a DID string or a {DID} object is passed, it simply returns that DID, so you can use this
2828+ # method to pass it an input string from the user which can be a DID or handle, without having to
2929+ # check which one it is.
3030+ #
3131+ # @param handle [String, DID] a domain handle (may start with an `@`) or a DID string
3232+ # @return [DID, nil] resolved DID if found, nil otherwise
3333+1434 def self.resolve_handle(handle)
1535 Resolver.new.resolve_handle(handle)
1636 end
17371818- attr_reader :type, :did, :resolved_by
3838+ # @return [Symbol] DID type (`:plc` or `:web`)
3939+ attr_reader :type
4040+4141+ # @return [String] DID identifier string
4242+ attr_reader :did
4343+4444+ # @return [Symbol, nil] `:dns` or `:http` if the DID was looked up using one of those methods
4545+ attr_reader :resolved_by
4646+4747+ alias to_s did
4848+4949+5050+ # Create a DID object from a DID string.
5151+ #
5252+ # @param did [String, DID] DID string or another DID object
5353+ # @param resolved_by [Symbol, nil] optionally, how the DID was looked up (`:dns` or `:http`)
5454+ # @raise [DIDError] when the DID format or type is invalid
19552056 def initialize(did, resolved_by = nil)
2157 if did.is_a?(DID)
···3672 @resolved_by = resolved_by
3773 end
38743939- alias to_s did
7575+ # Returns or looks up the DID document with the DID's identity details from an appropriate source.
7676+ # This method caches the document in a local variable if it's called again.
7777+ #
7878+ # @return [Document] resolved DID document
40794180 def document
4281 @document ||= get_document
4382 end
44838484+ # Looks up the DID document with the DID's identity details from an appropriate source.
8585+ # @return [Document] resolved DID document
8686+4587 def get_document
4688 Resolver.new.resolve_did(self)
4789 end
48909191+ # Returns the first verified handle assigned to this DID.
9292+ #
9393+ # Looks up the domain handles assigned to this DID in its DID document, checks if they are
9494+ # verified (i.e. assigned correctly to this DID using DNS TXT or .well-known) and returns
9595+ # the first handle that validates correctly, or nil if none matches.
9696+ #
9797+ # @return [String, nil] verified handle domain, if found
9898+4999 def get_verified_handle
50100 Resolver.new.get_verified_handle(document)
51101 end
52102103103+ # Fetches the PLC audit log (list of all previous operations) for a did:plc DID.
104104+ #
105105+ # @return [Array<PLCOperation>] list of PLC operations in the audit log
106106+ # @raise [DIDError] when the DID is not a did:plc
107107+53108 def get_audit_log
54109 if @type == :plc
55110 PLCImporter.new.fetch_audit_log(self)
···58113 end
59114 end
60115116116+ # Returns the domain portion of a did:web identifier.
117117+ #
118118+ # @return [String, nil] DID domain if the DID is a did:web, nil for did:plc
119119+61120 def web_domain
62121 did.gsub(/^did\:web\:/, '') if type == :web
63122 end
64123124124+ # Checks the status of the account/repo on its own PDS using the `getRepoStatus` endpoint.
125125+ #
126126+ # @param request_options [Hash] request options to override
127127+ # @option request_options [Integer] :timeout request timeout (default: 15)
128128+ # @option request_options [Integer] :max_redirects maximum number of redirects to follow (default: 5)
129129+ #
130130+ # @return [Symbol, nil] `:active`, or returned inactive status, or `nil` if account is not found
131131+ # @raise [APIError] when the response is invalid
132132+65133 def account_status(request_options = {})
66134 doc = self.document
67135 return nil if doc.pds_endpoint.nil?
···91159 end
92160 end
93161162162+ # Checks if the account is seen as active on its own PDS, using the `getRepoStatus` endpoint.
163163+ # This is a helper which calls the {#account_status} method and checks if the status is `:active`.
164164+ #
165165+ # @return [Boolean] true if the returned status is active
166166+ # @raise [APIError] when the response is invalid
167167+94168 def account_active?
95169 account_status == :active
96170 end
97171172172+ # Checks if the account exists its own PDS, using the `getRepoStatus` endpoint.
173173+ # This is a helper which calls the {#account_status} method and checks if the repo is found at all.
174174+ #
175175+ # @return [Boolean] true if the returned status is valid, false if repo is not found
176176+ # @raise [APIError] when the response is invalid
177177+98178 def account_exists?
99179 account_status != nil
100180 end
181181+182182+ # Compares the DID to another DID object or string.
183183+ #
184184+ # @param other [DID, String] other DID to compare with
185185+ # @return [Boolean] true if it's the same DID
101186102187 def ==(other)
103188 if other.is_a?(String)
+39-4
lib/didkit/document.rb
···11require_relative 'at_handles'
22+require_relative 'errors'
23require_relative 'resolver'
34require_relative 'service_record'
45require_relative 'services'
5667module DIDKit
88+99+ #
1010+ # Parsed DID document from a JSON file loaded from [plc.directory](https://plc.directory) or a did:web domain.
1111+ #
1212+ # Use {DID#document} or {Resolver#resolve_did} to fetch a DID document and return this object.
1313+ #
1414+715 class Document
88- class FormatError < StandardError
99- end
1010-1116 include AtHandles
1217 include Services
13181414- attr_reader :json, :did, :handles, :services
1919+ # @return [Hash] the complete JSON data of the DID document
2020+ attr_reader :json
2121+2222+ # @return [DID] the DID that this document describes
2323+ attr_reader :did
2424+2525+ # Returns a list of handles assigned to this DID in its DID document.
2626+ #
2727+ # Note: the handles aren't guaranteed to be verified (validated in the other direction).
2828+ # Use {#get_verified_handle} to find a handle that is correctly verified.
2929+ #
3030+ # @return [Array<String>]
3131+ attr_reader :handles
3232+3333+ # @return [Array<ServiceRecords>] service records like PDS details assigned to the DID
3434+ attr_reader :services
3535+3636+ # Creates a DID document object.
3737+ #
3838+ # @param did [DID] DID object
3939+ # @param json [Hash] DID document JSON
4040+ # @raise [FormatError] when required fields are missing or invalid.
15411642 def initialize(did, json)
1743 raise FormatError, "Missing id field" if json['id'].nil?
···2551 @handles = parse_also_known_as(json['alsoKnownAs'] || [])
2652 end
27535454+ # Returns the first verified handle assigned to the DID.
5555+ #
5656+ # Looks up the domain handles assigned to this DID in the DID document, checks if they are
5757+ # verified (i.e. assigned correctly to this DID using DNS TXT or .well-known) and returns
5858+ # the first handle that validates correctly, or nil if none matches.
5959+ #
6060+ # @return [String, nil] verified handle domain, if found
6161+2862 def get_verified_handle
2963 Resolver.new.get_verified_handle(self)
3064 end
6565+31663267 private
3368
+20-2
lib/didkit/errors.rb
···11module DIDKit
22- class DIDError < StandardError
33- end
4233+ #
44+ # Raised when an HTTP request returns a response with an error status.
55+ #
56 class APIError < StandardError
77+88+ # @return [Net::HTTPResponse] the returned HTTP response
69 attr_reader :response
7101111+ # @param response [Net::HTTPResponse] the returned HTTP response
812 def initialize(response)
913 @response = response
1014 super("APIError: #{response}")
1115 end
12161717+ # @return [Integer] HTTP status code
1318 def status
1419 response.code.to_i
1520 end
16212222+ # @return [String] HTTP response body
1723 def body
1824 response.body
1925 end
2626+ end
2727+2828+ #
2929+ # Raised when a string is not a valid DID or not of the right type.
3030+ #
3131+ class DIDError < StandardError
3232+ end
3333+3434+ #
3535+ # Raised when the loaded data has some missing or invalid fields.
3636+ #
3737+ class FormatError < StandardError
2038 end
2139end
+44-4
lib/didkit/plc_operation.rb
···11require 'time'
2233require_relative 'at_handles'
44+require_relative 'errors'
45require_relative 'service_record'
56require_relative 'services'
6778module DIDKit
88- class PLCOperation
99- class FormatError < StandardError
1010- end
1191010+ #
1111+ # Represents a single operation of changing a specific DID's data in the [plc.directory](https://plc.directory)
1212+ # (e.g. changing assigned handles or migrating to a different PDS).
1313+ #
1414+1515+ class PLCOperation
1216 include AtHandles
1317 include Services
14181515- attr_reader :json, :did, :cid, :seq, :created_at, :type, :handles, :services
1919+ # @return [Hash] the JSON from which the operation is parsed
2020+ attr_reader :json
2121+2222+ # @return [String] the DID which the operation concerns
2323+ attr_reader :did
2424+2525+ # @return [String] CID (Content Identifier) of the operation
2626+ attr_reader :cid
2727+2828+ # Returns a sequential number of the operation (only used in the new export API).
2929+ # @return [Integer, nil] sequential number of the operation
3030+ attr_reader :seq
3131+3232+ # @return [Time] time when the operation was created
3333+ attr_reader :created_at
3434+3535+ # Returns the `type` field of the operation (usually `"plc_operation"`).
3636+ # @return [String] the operation type
3737+ attr_reader :type
3838+3939+ # Returns a list of handles assigned to the DID in this operation.
4040+ #
4141+ # Note: the handles aren't guaranteed to be verified (validated in the other direction).
4242+ # Use {DID#get_verified_handle} or {Document#get_verified_handle} to find a handle that is
4343+ # correctly verified.
4444+ #
4545+ # @return [Array<String>]
4646+ attr_reader :handles
4747+4848+ # @return [Array<ServiceRecords>] service records like PDS details assigned to the DID
4949+ attr_reader :services
5050+5151+5252+ # Creates a PLCOperation object.
5353+ #
5454+ # @param json [Hash] operation JSON
5555+ # @raise [FormatError] when required fields are missing or invalid
16561757 def initialize(json)
1858 @json = json
···66require_relative 'requests'
7788module DIDKit
99+1010+ #
1111+ # A class which manages resolving of handles to DIDs and DIDs to DID documents.
1212+ #
1313+914 class Resolver
1515+ # These TLDs are not allowed in ATProto handles, so the resolver returns nil for them
1616+ # without trying to look them up.
1017 RESERVED_DOMAINS = %w(alt arpa example internal invalid local localhost onion test)
11181219 include Requests
13202121+ # @return [String, Array<String>] custom DNS nameserver(s) to use for DNS TXT lookups
1422 attr_accessor :nameserver
2323+2424+ # @param options [Hash] resolver options
2525+ # @option options [String, Array<String>] :nameserver custom DNS nameserver(s) to use (IP or an array of IPs)
2626+ # @option options [Integer] :timeout request timeout in seconds (default: 15)
2727+ # @option options [Integer] :max_redirects maximum number of redirects to follow (default: 5)
15281629 def initialize(options = {})
1730 @nameserver = options[:nameserver]
1831 @request_options = options.slice(:timeout, :max_redirects)
1932 end
20333434+ # Resolve a handle into a DID. Looks up the given ATProto domain handle using the DNS TXT method
3535+ # and the HTTP .well-known method and returns a DID if one is assigned using either of the methods.
3636+ #
3737+ # If a DID string or a {DID} object is passed, it simply returns that DID, so you can use this
3838+ # method to pass it an input string from the user which can be a DID or handle, without having to
3939+ # check which one it is.
4040+ #
4141+ # @param handle [String, DID] a domain handle (may start with an `@`) or a DID string
4242+ # @return [DID, nil] resolved DID if found, nil otherwise
4343+2144 def resolve_handle(handle)
2245 if handle.is_a?(DID) || handle =~ DID::GENERIC_REGEXP
2346 return DID.new(handle)
···3659 end
3760 end
38616262+ # Tries to resolve a handle into DID using the DNS TXT method.
6363+ #
6464+ # Checks the DNS records for a given domain for an entry `_atproto.#{domain}` whose value is
6565+ # a correct DID string.
6666+ #
6767+ # @param domain [String] a domain handle to look up
6868+ # @return [String, nil] resolved DID if found, nil otherwise
6969+3970 def resolve_handle_by_dns(domain)
4071 dns_records = Resolv::DNS.open(resolv_options) do |d|
4172 d.getresources("_atproto.#{domain}", Resolv::DNS::Resource::IN::TXT)
···5081 nil
5182 end
52838484+ # Tries to resolve a handle into DID using the HTTP .well-known method.
8585+ #
8686+ # Checks the `/.well-known/atproto-did` endpoint on the given domain to see if it returns
8787+ # a text file that contains a correct DID string.
8888+ #
8989+ # @param domain [String] a domain handle to look up
9090+ # @return [String, nil] resolved DID if found, nil otherwise
9191+5392 def resolve_handle_by_well_known(domain)
5493 url = "https://#{domain}/.well-known/atproto-did"
5594 response = get_response(url, @request_options)
···63102 nil
64103 end
65104105105+ # Resolve a DID to a DID document.
106106+ #
107107+ # Looks up the DID document with the DID's identity details from an appropriate source, i.e. either
108108+ # [plc.directory](https://plc.directory) for did:plc DIDs, or the did:web's domain for did:web DIDs.
109109+ #
110110+ # @param did [String, DID] DID string or object
111111+ # @return [Document] resolved DID document
112112+ # @raise [APIError] if an incorrect response is returned
113113+114114+ def resolve_did(did)
115115+ did = DID.new(did) if did.is_a?(String)
116116+117117+ did.type == :plc ? resolve_did_plc(did) : resolve_did_web(did)
118118+ end
119119+120120+ # Returns the first verified handle assigned to the given DID.
121121+ #
122122+ # Looks up the domain handles assigned to the DID in the DID document, checks if they are
123123+ # verified (i.e. assigned correctly to this DID using DNS TXT or .well-known) and returns
124124+ # the first handle that validates correctly, or nil if none matches.
125125+ #
126126+ # @param subject [String, DID, Document] a DID or its DID document
127127+ # @return [String, nil] verified handle domain, if found
128128+129129+ def get_verified_handle(subject)
130130+ document = subject.is_a?(Document) ? subject : resolve_did(subject)
131131+132132+ first_verified_handle(document.did, document.handles)
133133+ end
134134+135135+ # Returns the first handle from the list that resolves back to the given DID.
136136+ #
137137+ # @param did [DID, String] DID to verify the handles against
138138+ # @param handles [Array<String>] handles to check
139139+ # @return [String, nil] a verified handle, if found
140140+141141+ def first_verified_handle(did, handles)
142142+ handles.detect { |h| resolve_handle(h) == did.to_s }
143143+ end
144144+145145+146146+ private
147147+66148 def resolv_options
67149 options = Resolv::DNS::Config.default_config_hash.dup
68150 options[:nameserver] = nameserver if nameserver
···78160 text.lines.length == 1 && text =~ DID::GENERIC_REGEXP ? text : nil
79161 end
801628181- def resolve_did(did)
8282- did = DID.new(did) if did.is_a?(String)
8383-8484- did.type == :plc ? resolve_did_plc(did) : resolve_did_web(did)
8585- end
8686-87163 def resolve_did_plc(did)
88164 json = get_json("https://plc.directory/#{did}", content_type: /^application\/did\+ld\+json(;.+)?$/)
89165 Document.new(did, json)
···92168 def resolve_did_web(did)
93169 json = get_json("https://#{did.web_domain}/.well-known/did.json")
94170 Document.new(did, json)
9595- end
9696-9797- def get_verified_handle(subject)
9898- document = subject.is_a?(Document) ? subject : resolve_did(subject)
9999-100100- first_verified_handle(document.did, document.handles)
101101- end
102102-103103- def first_verified_handle(did, handles)
104104- handles.detect { |h| resolve_handle(h) == did.to_s }
105171 end
106172 end
107173end
+21-3
lib/didkit/service_record.rb
···22require_relative 'errors'
3344module DIDKit
55+66+ # A parsed service record from either a DID document's `service` field or a PLC directory
77+ # operation's `services` field.
88+59 class ServiceRecord
66- class FormatError < StandardError
77- end
81099- attr_reader :key, :type, :endpoint
1111+ # Returns the service's identifier (without `#`), like "atproto_pds".
1212+ # @return [String] service's identifier
1313+ attr_reader :key
1414+1515+ # Returns the service's type field, like "AtprotoPersonalDataServer".
1616+ # @return [String] service's type
1717+ attr_reader :type
1818+1919+ # @return [String] service's endpoint URL
2020+ attr_reader :endpoint
2121+2222+ # Create a service record from DID document fields.
2323+ #
2424+ # @param key [String] service identifier (without `#`)
2525+ # @param type [String] service type
2626+ # @param endpoint [String] service endpoint URL
2727+ # @raise [FormatError] when the endpoint is not a valid URI
10281129 def initialize(key, type, endpoint)
1230 begin
+40
lib/didkit/services.rb
···11require 'uri'
2233module DIDKit
44+55+ #
66+ # @api private
77+ #
88+49 module Services
1010+1111+ # Finds a service entry matching the given key and type.
1212+ #
1313+ # @api public
1414+ # @param key [String] service key in the DID document
1515+ # @param type [String] service type identifier
1616+ # @return [ServiceRecord, nil] matching service record, if found
1717+518 def get_service(key, type)
619 @services&.detect { |s| s.key == key && s.type == type }
720 end
8212222+ # Returns the PDS service endpoint, if present.
2323+ #
2424+ # If the DID has an `#atproto_pds` service declared in its `service` section,
2525+ # returns the URL in its `serviceEndpoint` field. In other words, this is the URL
2626+ # of the PDS assigned to a given user, which stores the user's account and repo.
2727+ #
2828+ # @api public
2929+ # @return [String, nil] PDS service endpoint URL
3030+931 def pds_endpoint
1032 @pds_endpoint ||= get_service('atproto_pds', 'AtprotoPersonalDataServer')&.endpoint
1133 end
3434+3535+ # Returns the labeler service endpoint, if present.
3636+ #
3737+ # If the DID has an `#atproto_labeler` service declared in its `service` section,
3838+ # returns the URL in its `serviceEndpoint` field.
3939+ #
4040+ # @api public
4141+ # @return [String, nil] labeler service endpoint URL
12421343 def labeler_endpoint
1444 @labeler_endpoint ||= get_service('atproto_labeler', 'AtprotoLabeler')&.endpoint
1545 end
16464747+ # Returns the hostname of the PDS service, if present.
4848+ #
4949+ # @api public
5050+ # @return [String, nil] hostname of the PDS endpoint URL
5151+1752 def pds_host
1853 pds_endpoint&.then { |x| URI(x).host }
1954 end
5555+5656+ # Returns the hostname of the labeler service, if present.
5757+ #
5858+ # @api public
5959+ # @return [String, nil] hostname of the labeler endpoint URL
20602161 def labeler_host
2262 labeler_endpoint&.then { |x| URI(x).host }
+7-7
spec/document_spec.rb
···4141 it 'should raise a format error' do
4242 expect {
4343 subject.new(did, json)
4444- }.to raise_error(DIDKit::Document::FormatError)
4444+ }.to raise_error(DIDKit::FormatError)
4545 end
4646 end
4747···5151 it 'should raise a format error' do
5252 expect {
5353 subject.new(did, json)
5454- }.to raise_error(DIDKit::Document::FormatError)
5454+ }.to raise_error(DIDKit::FormatError)
5555 end
5656 end
5757···6161 it 'should raise a format error' do
6262 expect {
6363 subject.new(did, json)
6464- }.to raise_error(DIDKit::Document::FormatError)
6464+ }.to raise_error(DIDKit::FormatError)
6565 end
6666 end
6767···7171 it 'should raise an AtHandles format error' do
7272 expect {
7373 subject.new(did, json)
7474- }.to raise_error(DIDKit::AtHandles::FormatError)
7474+ }.to raise_error(DIDKit::FormatError)
7575 end
7676 end
7777···8181 it 'should raise an AtHandles format error' do
8282 expect {
8383 subject.new(did, json)
8484- }.to raise_error(DIDKit::AtHandles::FormatError)
8484+ }.to raise_error(DIDKit::FormatError)
8585 end
8686 end
8787···106106 it 'should raise a format error' do
107107 expect {
108108 subject.new(did, json)
109109- }.to raise_error(DIDKit::Document::FormatError)
109109+ }.to raise_error(DIDKit::FormatError)
110110 end
111111 end
112112···116116 it 'should raise a format error' do
117117 expect {
118118 subject.new(did, json)
119119- }.to raise_error(DIDKit::Document::FormatError)
119119+ }.to raise_error(DIDKit::FormatError)
120120 end
121121 end
122122
+16-16
spec/plc_operation_spec.rb
···2727 let(:json) { [base_json] }
28282929 it 'should raise a format error' do
3030- expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError)
3030+ expect { subject.new(json) }.to raise_error(DIDKit::FormatError)
3131 end
3232 end
3333···3535 let(:json) { base_json.tap { |h| h.delete('did') }}
36363737 it 'should raise a format error' do
3838- expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError)
3838+ expect { subject.new(json) }.to raise_error(DIDKit::FormatError)
3939 end
4040 end
4141···4343 let(:json) { base_json.merge('did' => 123) }
44444545 it 'should raise a format error' do
4646- expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError)
4646+ expect { subject.new(json) }.to raise_error(DIDKit::FormatError)
4747 end
4848 end
4949···5151 let(:json) { base_json.merge('did' => 'foobar') }
52525353 it 'should raise a format error' do
5454- expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError)
5454+ expect { subject.new(json) }.to raise_error(DIDKit::FormatError)
5555 end
5656 end
5757···5959 let(:json) { base_json.tap { |h| h.delete('cid') }}
60606161 it 'should raise a format error' do
6262- expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError)
6262+ expect { subject.new(json) }.to raise_error(DIDKit::FormatError)
6363 end
6464 end
6565···6767 let(:json) { base_json.merge('cid' => 700) }
68686969 it 'should raise a format error' do
7070- expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError)
7070+ expect { subject.new(json) }.to raise_error(DIDKit::FormatError)
7171 end
7272 end
7373···7575 let(:json) { base_json.tap { |h| h.delete('createdAt') }}
76767777 it 'should raise a format error' do
7878- expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError)
7878+ expect { subject.new(json) }.to raise_error(DIDKit::FormatError)
7979 end
8080 end
8181···8383 let(:json) { base_json.merge('createdAt' => 123) }
84848585 it 'should raise a format error' do
8686- expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError)
8686+ expect { subject.new(json) }.to raise_error(DIDKit::FormatError)
8787 end
8888 end
8989···9191 let(:json) { base_json.tap { |h| h.delete('operation') }}
92929393 it 'should raise a format error' do
9494- expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError)
9494+ expect { subject.new(json) }.to raise_error(DIDKit::FormatError)
9595 end
9696 end
9797···9999 let(:json) { base_json.merge('operation' => 'invalid') }
100100101101 it 'should raise a format error' do
102102- expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError)
102102+ expect { subject.new(json) }.to raise_error(DIDKit::FormatError)
103103 end
104104 end
105105···107107 let(:json) { base_json.tap { |h| h['operation'].delete('type') }}
108108109109 it 'should raise a format error' do
110110- expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError)
110110+ expect { subject.new(json) }.to raise_error(DIDKit::FormatError)
111111 end
112112 end
113113···152152 it 'should raise an AtHandles format error' do
153153 expect {
154154 subject.new(json)
155155- }.to raise_error(DIDKit::AtHandles::FormatError)
155155+ }.to raise_error(DIDKit::FormatError)
156156 end
157157 end
158158···162162 it 'should raise an AtHandles format error' do
163163 expect {
164164 subject.new(json)
165165- }.to raise_error(DIDKit::AtHandles::FormatError)
165165+ }.to raise_error(DIDKit::FormatError)
166166 end
167167 end
168168···187187 let(:json) { base_json.tap { |h| h['operation'].delete('services') }}
188188189189 it 'should raise a format error' do
190190- expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError)
190190+ expect { subject.new(json) }.to raise_error(DIDKit::FormatError)
191191 end
192192 end
193193···205205 }
206206207207 it 'should raise a format error' do
208208- expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError)
208208+ expect { subject.new(json) }.to raise_error(DIDKit::FormatError)
209209 end
210210 end
211211···225225 }
226226227227 it 'should raise a format error' do
228228- expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError)
228228+ expect { subject.new(json) }.to raise_error(DIDKit::FormatError)
229229 end
230230 end
231231